第 08 章:编辑器与工具集成
第 08 章:编辑器与工具集成
8.1 集成概览
Hunspell 被广泛集成在各种编辑器、办公套件和自动化工具中。本章详细讲解各平台的配置方法。
| 工具 | 集成方式 | 配置复杂度 |
|---|
| LibreOffice | 内置引擎 | ★ |
| Firefox / Thunderbird | 内置引擎 | ★ |
| VS Code | 扩展 | ★★ |
| Emacs | ispell/flyspell | ★★★ |
| Vim / Neovim | 插件 | ★★ |
| Sublime Text | 包 | ★★ |
| CI/CD(GitHub Actions) | 命令行 | ★★ |
| pre-commit | 钩子 | ★★ |
| pandoc | 外部工具 | ★ |
8.2 LibreOffice
8.2.1 内置配置
LibreOffice 自带 Hunspell 引擎,配置通过菜单完成:
工具 → 语言 → 更多语言选项
→ 语言设置
→ 写作辅助
→ 可用语言模块 → Hunspell
8.2.2 安装额外词典
# 方法 1: 系统级安装(推荐)
sudo apt install hunspell-fr hunspell-de-de hunspell-es
# 方法 2: 通过 LibreOffice 扩展管理器
# 下载 .oxt 文件 → 工具 → 扩展管理器 → 添加
8.2.3 添加自定义词典
工具 → 语言 → 更多语言选项
→ 写作辅助
→ 自定义词典
→ 新建 → 输入词典名
→ 添加单词
自定义词典存储位置:
# Linux
~/.config/libreoffice/4/user/wordbook/
# 文件格式(.dic)
# 每行一个单词
Docker
Kubernetes
API
JSON
8.2.4 多语言文档
LibreOffice 支持在同一文档中混合使用多种语言的拼写检查:
- 选中段落
工具 → 语言 → 选中文本的语言- 选择对应语言
# 也可以通过段落样式设置语言
# 格式 → 样式 → 编辑样式 → 字体 → 语言
8.2.5 排除单词
# 方法 1: 右键 → 全部接受
# 方法 2: 右键 → 添加到词典
# 方法 3: 编辑自定义词典文件
8.2.6 LibreOffice 词典路径
# 系统词典
/usr/share/hunspell/
# 用户词典
~/.config/libreoffice/4/user/wordbook/
# LibreOffice 扩展安装的词典
~/.config/libreoffice/4/user/uno_packages/cache/
8.3 Firefox / Thunderbird
8.3.1 内置拼写检查
Firefox 和 Thunderbird 内置 Hunspell 引擎,默认启用。
Firefox 设置:
about:preferences → 常规 → 语言
→ 拼写检查 → 使用拼写检查
→ 选择词典语言
8.3.2 添加词典
Firefox → 右键文本框 → 语言 → 添加词典
→ 跳转到 Firefox 附加组件 → 语言工具
→ 安装所需语言的词典
# Firefox 词典扩展列表
# https://addons.mozilla.org/en-US/firefox/language-tools/
8.3.3 自定义词典管理
# Firefox 用户词典文件位置
~/.mozilla/firefox/<profile>/persdict.dat
# 文件格式:每行一个单词
Hunspell
API
JSON
# 管理自定义词典
Firefox → 设置 → 常规 → 语言 → 编辑词典
→ 添加/删除单词
8.3.4 Thunderbird 配置
Thunderbird → 编辑 → 首选项 → 编辑器
→ 拼写检查
→ 启用实时拼写检查
→ 选择词典语言
8.4 VS Code
8.4.1 安装拼写检查扩展
# 最流行的扩展:Code Spell Checker
# 扩展 ID: streetsidesoftware.code-spell-checker
# 通过命令面板安装
# Ctrl+Shift+P → Extensions: Install Extension → 搜索 "spell"
8.4.2 基本配置
// .vscode/settings.json
{
// 语言设置
"cSpell.language": "en",
// 启用/禁用文件类型
"cSpell.enableFileTypes": [
"markdown",
"plaintext",
"latex",
"restructuredtext"
],
// 忽略的文件模式
"cSpell.ignorePaths": [
"node_modules",
"package-lock.json",
"*.min.js",
"*.svg"
],
// 最小单词长度
"cSpell.minWordLength": 3,
// 大小写敏感
"cSpell.caseSensitive": true
}
8.4.3 自定义词典配置
// .vscode/settings.json
{
"cSpell.customDictionaries": {
// 工作区词典(推荐,可以提交到 Git)
"workspace": {
"name": "workspace",
"path": "${workspaceFolder}/.vscode/dictionary.txt",
"addWords": true,
"scope": "workspace"
},
// 用户词典
"user": {
"name": "user",
"path": "~/.cspell/user-words.txt",
"addWords": true
},
// 项目特定词典
"project": {
"name": "project",
"path": "${workspaceFolder}/.hunspell/project.dic",
"addWords": true
}
}
}
8.4.4 项目词典文件
# .vscode/dictionary.txt
# 项目术语词典
TypeScript
JavaScript
Docker
Kubernetes
API
JSON
HTTP
GraphQL
gRPC
webhook
microservice
middleware
refactor
async
await
callback
closure
polymorphism
8.4.5 通过 cspell.json 配置
// cspell.json(放在项目根目录)
{
"version": "0.2",
"language": "en",
"words": [
"Docker",
"Kubernetes",
"TypeScript",
"GraphQL",
"gRPC",
"webhook"
],
"flagWords": [
"teh",
"adn",
"hte"
],
"ignoreWords": [],
"patterns": [
{
"name": "markdown-code-block",
"pattern": "/```[\\s\\S]*?```/g",
"description": "Markdown 代码块"
},
{
"name": "url",
"pattern": "/(https?|ftp):[^\\s]+/gi",
"description": "URL 链接"
}
],
"ignoreRegExpList": [
"markdown-code-block",
"url",
"/`[^`]+`/g"
],
"languageSettings": [
{
"languageId": "markdown",
"dictionaries": ["en-US", "workspace"]
},
{
"languageId": "latex",
"dictionaries": ["en-US", "latex"]
}
],
"dictionaries": [
"en-US",
"companies",
"softwareTerms"
],
"import": [
"@cspell/dict-en-us/cspell-ext.json",
"@cspell/dict-software-terms/cspell-ext.json"
]
}
8.4.6 快捷操作
| 快捷键 | 操作 |
|---|
Ctrl+. | 显示拼写错误快速修复 |
Ctrl+Shift+P → cSpell | 打开拼写检查命令面板 |
右键 → Add to Dictionary | 添加到词典 |
右键 → Ignore Word | 忽略当前词 |
8.4.7 VS Code 任务集成
// .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Spell Check",
"type": "shell",
"command": "hunspell",
"args": [
"-d", "en_US",
"-p", ".hunspell/project.dic",
"-l",
"${workspaceFolder}/**/*.md"
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}
8.5 Emacs
8.5.1 配置 flyspell
;; init.el — Emacs flyspell 配置
;; 启用 flyspell(实时拼写检查)
(setq ispell-program-name "hunspell")
(setq ispell-dictionary "en_US")
;; flyspell 在特定模式中启用
(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'org-mode-hook 'flyspell-mode)
(add-hook 'markdown-mode-hook 'flyspell-mode)
(add-hook 'latex-mode-hook 'flyspell-mode)
;; 编程模式中只检查注释和字符串
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
;; 自定义词典路径
(setq ispell-personal-dictionary "~/.hunspell_personal")
8.5.2 多语言配置
;; 多语言切换
(defun my-switch-hunspell-dict (lang)
"切换 Hunspell 词典"
(interactive
(list (completing-read "语言: "
'("en_US" "en_GB" "fr" "de_DE" "es" "zh_CN"))))
(ispell-change-dictionary lang)
(flyspell-mode 1) ;; 重新启动 flyspell
(message "切换到词典: %s" lang))
(global-set-key (kbd "C-c s l") 'my-switch-hunspell-dict)
;; 快速添加单词到个人词典
(defun my-add-word-to-dict ()
"将光标下的单词添加到个人词典"
(interactive)
(let ((word (word-at-point)))
(when word
(ispell-send-string (concat "*" word "\n"))
(message "已添加: %s" word))))
(global-set-key (kbd "C-c s a") 'my-add-word-to-dict)
8.5.3 flyspell 快捷键
| 快捷键 | 操作 |
|---|
M-$ | 修正光标处的拼写错误 |
C-M-i | 自动补全拼写建议 |
C-, | 跳到下一个拼写错误 |
C-. | 跳到上一个拼写错误 |
8.5.4 Hunspell + aspell 混合配置
;; 优先使用 hunspell,回退到 aspell
(cond
((executable-find "hunspell")
(setq ispell-program-name "hunspell")
(setq ispell-extra-args '("-d" "en_US")))
((executable-find "aspell")
(setq ispell-program-name "aspell")
(setq ispell-extra-args '("--sug-mode=ultra" "--lang=en_US"))))
8.6 Vim / Neovim
8.6.1 内置拼写检查
" 启用内置拼写检查(Vim 7+)
set spell
set spelllang=en_us
" 切换语言
set spelllang=fr
" 多语言
set spelllang=en_us,fr,de
" 拼写检查样式
highlight SpellBad cterm=underline gui=underline
highlight SpellCap cterm=underline gui=underline
8.6.2 拼写检查快捷键
| 快捷键 | 操作 |
|---|
]s | 跳到下一个拼写错误 |
[s | 跳到上一个拼写错误 |
z= | 显示拼写建议列表 |
zg | 将单词加入好词词典 |
zw | 将单词标记为错误 |
zug | 撤销 zg |
zuw | 撤销 zw |
8.6.3 个人词典管理
" Vim 好词词典位置
" ~/.vim/spell/en.utf-8.add
" 使用自定义词典路径
set spellfile=.vim/spell/custom.utf-8.add
" 查看当前使用的词典
set spell?
8.6.4 vim-spellsuggest 插件
" 使用 fzf 提供更好的拼写建议界面
Plug 'junegunn/fzf.vim'
function! FzfSpellSuggest()
let suggestions = spellsuggest(expand('<cword>'))
call fzf#run({
\ 'source': suggestions,
\ 'sink': function('FzfSpellReplace'),
\ 'options': '+m',
\ 'down': '30%'
\ })
endfunction
function! FzfSpellReplace(word)
exe 'normal! ciw'.a:word
endfunction
nnoremap z= :call FzfSpellSuggest()<CR>
8.6.5 Neovim 集成 (nvim-spell)
-- init.lua — Neovim 拼写检查配置
vim.opt.spell = true
vim.opt.spelllang = "en_us"
-- 自定义词典
vim.opt.spellfile = vim.fn.stdpath("config") .. "/spell/custom.utf-8.add"
-- 快速添加单词的快捷键
vim.keymap.set('n', '<leader>sa', 'zg', { desc = "添加到词典" })
vim.keymap.set('n', '<leader>su', 'zug', { desc = "撤销添加" })
vim.keymap.set('n', '<leader>s=', 'z=', { desc = "显示建议" })
8.7 Sublime Text
8.7.1 安装词典包
Ctrl+Shift+P → Package Control: Install Package
→ 搜索 "Dictionaries" 或 "Spell Check"
8.7.2 配置
// Preferences → Settings
{
// 启用拼写检查
"spell_check": true,
// 词典路径(默认使用系统词典)
"dictionary": "Packages/Language - English/en_US.dic",
// 拼写检查触发间隔(毫秒)
"dictionary_close_on_save": false
}
8.7.3 快捷键
| 快捷键 | 操作 |
|---|
F6 | 切换拼写检查 |
Ctrl+Shift+; | 跳到下一个错误 |
Ctrl+Shift+, | 拼写建议 |
8.8 CI/CD 集成
8.8.1 GitHub Actions
# .github/workflows/spellcheck.yml
name: Spell Check
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Hunspell
run: |
sudo apt-get update
sudo apt-get install -y hunspell hunspell-en-us
- name: Run spell check
run: |
# 检查所有 Markdown 文件
ERRORS=""
while IFS= read -r -d '' file; do
file_errors=$(hunspell -l -d en_US -p .hunspell/project.dic "$file" 2>/dev/null | sort -u)
if [ -n "$file_errors" ]; then
ERRORS="$ERRORS\n$file:\n$file_errors"
fi
done < <(find . -name "*.md" -not -path "./.git/*" -print0)
if [ -n "$ERRORS" ]; then
echo "::error::发现拼写错误"
echo -e "$ERRORS"
exit 1
fi
echo "✓ 拼写检查通过"
- name: Generate spell report
if: failure()
run: |
echo "## 拼写检查报告" > spell_report.md
echo "" >> spell_report.md
while IFS= read -r -d '' file; do
errors=$(hunspell -l -d en_US -p .hunspell/project.dic "$file" 2>/dev/null | sort -u)
if [ -n "$errors" ]; then
echo "### $file" >> spell_report.md
echo '```' >> spell_report.md
echo "$errors" >> spell_report.md
echo '```' >> spell_report.md
fi
done < <(find . -name "*.md" -not -path "./.git/*" -print0)
cat spell_report.md
8.8.2 GitLab CI
# .gitlab-ci.yml
stages:
- lint
spellcheck:
stage: lint
image: ubuntu:22.04
before_script:
- apt-get update
- apt-get install -y hunspell hunspell-en-us
script:
- |
ERRORS=$(find docs/ -name "*.md" -exec cat {} \; | \
hunspell -d en_US -p .hunspell/project.dic -l | sort -u)
if [ -n "$ERRORS" ]; then
echo "拼写错误:"
echo "$ERRORS"
exit 1
fi
artifacts:
when: on_failure
paths:
- spell_report.txt
8.8.3 pre-commit 框架集成
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: hunspell-check
name: Hunspell Spell Check
entry: hunspell -l -d en_US -p .hunspell/project.dic
language: system
files: '\.(md|txt|rst)$'
pass_filenames: true
require_serial: false
# 安装 pre-commit
pip install pre-commit
# 安装钩子
pre-commit install
# 手动运行
pre-commit run hunspell-check --all-files
8.8.4 自定义 CI 脚本
#!/bin/bash
# ci-spellcheck.sh — CI 拼写检查脚本
set -euo pipefail
DICT="${DICT:-en_US}"
PERSONAL_DICT="${PERSONAL_DICT:-.hunspell/project.dic}"
FILE_PATTERN="${FILE_PATTERN:-*.md}"
EXIT_CODE=0
REPORT=""
echo "=== CI 拼写检查 ==="
echo "词典: $DICT"
echo "个人词典: $PERSONAL_DICT"
echo "文件模式: $FILE_PATTERN"
echo ""
# 收集所有错误
while IFS= read -r -d '' file; do
errors=$(hunspell -l -d "$DICT" -p "$PERSONAL_DICT" "$file" 2>/dev/null | sort -u)
if [ -n "$errors" ]; then
error_count=$(echo "$errors" | wc -l)
echo "✗ $file ($error_count 个错误)"
REPORT="$REPORT\n## $file\n\`\`\`\n$errors\n\`\`\`\n"
EXIT_CODE=1
else
echo "✓ $file"
fi
done < <(find . -type f -name "$FILE_PATTERN" -not -path "./.git/*" -print0)
echo ""
# 生成报告
if [ "$EXIT_CODE" -ne 0 ]; then
echo "=== 拼写错误报告 ==="
echo -e "$REPORT"
# 在 GitHub Actions 中创建注释
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
echo "## 🔤 拼写检查报告" >> "$GITHUB_STEP_SUMMARY"
echo -e "$REPORT" >> "$GITHUB_STEP_SUMMARY"
fi
fi
exit $EXIT_CODE
8.9 Pandoc 集成
8.9.1 Pandoc 拼写检查
# Pandoc 可以配合 hunspell 进行拼写检查
# 将文档转为纯文本后检查
# Markdown → 纯文本 → hunspell
pandoc -t plain input.md | hunspell -d en_US -l
# 只检查 Markdown 中的文本内容(忽略标记)
pandoc -t markdown --wrap=none input.md | \
sed 's/\[.*\](.*)//g' | # 移除链接
sed 's/\*\*//g' | # 移除粗体
sed 's/\*//g' | # 移除斜体
hunspell -d en_US -l
8.9.2 Pandoc 过滤器
#!/usr/bin/env python3
"""pandoc_spellcheck.py — Pandoc 拼写检查过滤器"""
import panflute as pf
import subprocess
def spellcheck(elem, doc):
"""检查文本元素的拼写"""
if isinstance(elem, pf.Str) and len(elem.text) >= 3:
# 只检查纯文本(非代码、非链接)
if not any(isinstance(parent, (pf.Code, pf.CodeBlock, pf.Link))
for parent in [elem.parent]):
result = subprocess.run(
["hunspell", "-d", "en_US", "-l"],
input=elem.text, capture_output=True, text=True
)
if result.stdout.strip():
pf.debug(f"拼写错误: {elem.text} (在 {elem.parent})")
elem.text = f"⚠{elem.text}⚠"
return elem
if __name__ == "__main__":
pf.run_filter(spellcheck)
# 使用过滤器
pandoc -F pandoc_spellcheck.py input.md -o output.html
8.10 容器化集成
8.10.1 Docker 拼写检查镜像
# Dockerfile
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
hunspell \
hunspell-en-us \
hunspell-fr \
hunspell-de-de \
&& rm -rf /var/lib/apt/lists/*
COPY .hunspell/project.dic /opt/dictionaries/
COPY .hunspell/project.aff /opt/dictionaries/
WORKDIR /docs
ENTRYPOINT ["hunspell"]
CMD ["-d", "en_US", "-p", "/opt/dictionaries/project.dic", "-l"]
# 构建
docker build -t spellcheck .
# 使用
docker run --rm -v $(pwd):/docs spellcheck
docker run --rm -v $(pwd):/docs spellcheck -d fr -l
8.10.2 Docker Compose 配置
# docker-compose.yml
version: '3.8'
services:
spellcheck:
build: .
volumes:
- .:/docs
- ./.hunspell:/opt/dictionaries
command: >
hunspell -d en_US
-p /opt/dictionaries/project.dic
-l *.md
8.11 各平台词典路径速查
| 平台 | 词典路径 |
|---|
| Ubuntu/Debian | /usr/share/hunspell/ |
| Fedora | /usr/share/hunspell/ |
| Arch Linux | /usr/share/hunspell/ |
| macOS (Homebrew) | /usr/local/share/hunspell/ 或 /opt/homebrew/share/hunspell/ |
| Windows (MSYS2) | C:\msys64\mingw64\share\hunspell\ |
| LibreOffice 用户 | ~/.config/libreoffice/4/user/wordbook/ |
| Firefox 用户 | ~/.mozilla/firefox/<profile>/persdict.dat |
| VS Code | ~/.cspell/ 或项目 .vscode/dictionary.txt |
| Emacs | ~/.hunspell_personal 或自定义路径 |
8.12 本章小结
| 工具 | 推荐扩展/配置 | 自定义词典方式 |
|---|
| LibreOffice | 内置 | 扩展管理器 + 用户词典 |
| Firefox | 内置 | about:preferences → 语言 |
| VS Code | Code Spell Checker | cSpell.json + .vscode/settings.json |
| Emacs | flyspell | ispell-personal-dictionary |
| Vim/Neovim | 内置 :set spell | spellfile |
| Sublime Text | Dictionaries 包 | 用户设置 |
| CI/CD | hunspell CLI | 项目词典 + pre-commit |
扩展阅读