]> git.phdru.name Git - dotfiles.git/blob - .vim/misc/ispell.vim
Initial import
[dotfiles.git] / .vim / misc / ispell.vim
1 " Define `Ispell' language and personal dictionary, used in several places below
2 let IspellLang = 'russian'
3 let PersonalDict = '~/.ispell_' . IspellLang
4
5 " Try to avoid misspelling words in the first place -- have the insert mode
6 " <Ctrl>+N/<Ctrl>+P keys perform completion on partially-typed words by
7 " checking the Linux word list and the personal `Ispell' dictionary; sort out
8 " case sensibly (so that words at starts of sentences can still be completed
9 " with words that are in the dictionary all in lower case):
10 execute 'set dictionary+=' . '~/.ispell_english'
11 execute 'set dictionary+=' . PersonalDict
12 set dictionary+=/usr/dict/words
13
14 " Spell checking operations are defined next.  They are all set to normal mode
15 " keystrokes beginning \s but function keys are also mapped to the most common
16 " ones.  The functions referred to are defined at the end of this .vimrc.
17
18 " \se ("spelling english") saves the current file then spell checks it
19 " interactively through `Ispell' and reloads the corrected version:
20 nmap \se :call RecodeAndSpellcheck("")<CR>
21
22 " \sr ("spelling russian") converts the file to the locale encoding,
23 " saves it, then spell checks it interactively through `Ispell',
24 " reloads the corrected version and converts it back to the original encoding:
25 nmap \sr :call RecodeAndSpellcheck(IspellLang)<CR>
26
27 " \sl ("spelling list") lists all spelling mistakes in the current buffer,
28 " but excludes any in news/mail headers or in ("> ") quoted text:
29 execute 'nmap \sl :up! grep -v "^>" <Bar> grep -E -v "^[[:alpha:]-]+: " ' .
30 \ '<Bar> ispell -l -d ' . IspellLang . ' <Bar> sort <Bar> uniq<CR>'
31
32 " \sh ("spelling highlight") highlights (in red) all misspelt words in the
33 " current buffer, and also excluding the possessive forms of any valid words
34 " (e.g. "Lizzy's" won't be highlighted if "Lizzy" is in the dictionary); with
35 " mail and news messages it ignores headers and quoted text; for HTML it
36 " ignores tags and only checks words that will appear, and turns off other
37 " syntax highlighting to make the errors more apparent [function at end of
38 " file]:
39 nmap \sh :call HighlightSpellingErrors()<CR><CR><CR>
40
41 " \sc ("spelling clear") clears all highlighted misspellings; for HTML it
42 " restores regular syntax highlighting:
43 nmap \sc :if &ft == 'html' <Bar> sy on <Bar>
44 \ else <Bar> :sy clear SpellError <Bar> endif<CR>
45
46 " \sa ("spelling add") adds the word at the cursor position to the personal
47 " dictionary (but for possessives adds the base word, so that when the cursor
48 " is on "Ceri's" only "Ceri" gets added to the dictionary), and stops
49 " highlighting that word as an error (if appropriate) [function at end of
50 " file]:
51 nmap \sa :call AddWordToDictionary()<CR><CR>
52
53
54 " Functions referred to above
55
56 function! HighlightSpellingErrors()
57 " highlights spelling errors in the current window; used for the \sh operation
58 " defined above;
59 " requires the ispell, sort, and uniq commands to be in the path;
60 " requires the global variable IspellLang to be defined above, and to contain
61 " the preferred `Ispell' language;
62 " for mail/news messages, requires the grep command to be in the path;
63 " for HTML documents, saves the file to disk and requires the lynx command to
64 " be in the path
65 "
66 " by Smylers  http://www.stripey.com/vim/
67 " (inspired by Krishna Gadepalli and Neil Schemenauer's vimspell.sh)
68 "
69 " 2000 Jun 1: for `Vim' 5.6
70
71 " for HTML files, remove all current syntax highlighting (so that
72 " misspellings show up clearly), and note it's HTML for future reference:
73    if &filetype == 'html'
74       let HTML = 1
75       syntax clear
76
77       " for everything else, simply remove any previously-identified spelling
78       " errors (and corrections):
79    else
80       let HTML = 0
81       if hlexists('SpellError')
82          syntax clear SpellError
83       endif
84       if hlexists('Normal')
85          syntax clear Normal
86       endif
87    endif
88
89    " form a command that has the text to be checked piping through standard
90    " output; for HTML files this involves saving the current file and processing
91    " it with `Lynx'; for everything else, use all the buffer except quoted text
92    " and mail/news headers:
93    update
94    if HTML
95       let PipeCmd = '! lynx --raw --dump --nolist % |'
96    else
97       let PipeCmd = '!'
98       if &filetype == 'mail'
99          let PipeCmd = PipeCmd . ' grep -v "^> " | grep -E -v "^[[:alpha:]-]+:" |'
100       endif
101    endif
102
103    " execute that command, then generate a unique list of misspelt words and
104    " store it in a temporary file:
105    let ErrorsFile = tempname()
106    execute PipeCmd . ' ispell -l -d '. g:IspellLang .
107       \ ' | sort | uniq > ' . ErrorsFile
108
109    " open that list of words in another window:
110    execute 'split ' . ErrorsFile
111
112    " for every word in that list ending with "'s", check if the root form
113    " without the "'s" is in the dictionary, and if so remove the word from the
114    " list:
115    global /'s$/ execute 'read ! echo ' . expand('<cword>') .
116    \ ' | ispell -l -d ' . g:IspellLang | delete
117    " (If the root form is in the dictionary, ispell -l will have no output so
118    " nothing will be read in, the cursor will remain in the same place and the
119    " :delete will delete the word from the list.  If the root form is not in the
120    " dictionary, then ispell -l will output it and it will be read on to a new
121    " line; the delete command will then remove that misspelt root form, leaving
122    " the original possessive form in the list!)
123
124    " only do anything if there are some misspellings:
125    if strlen(getline('.')) > 0
126
127       " if (previously noted as) HTML, replace each non-alphanum char with a
128       " regexp that matches either that char or a &...; entity:
129       if HTML
130          % substitute /\W/\\(&\\|\&\\(#\\d\\{2,4}\\|\w\\{2,8}\\);\\)/e
131       endif
132
133       " turn each mistake into a `Vim' command to place it in the SpellError
134       " syntax highlighting group:
135       % substitute /^/syntax match SpellError !\\</
136       % substitute /$/\\>!/
137    endif
138
139    " save and close that file (so switch back to the one being checked):
140    exit
141
142    " make syntax highlighting case-sensitive, then execute all the match
143    " commands that have just been set up in that temporary file, delete it, and
144    " highlight all those words in red:
145    syntax case match
146    execute 'source ' . ErrorsFile
147    call delete(ErrorsFile)
148    highlight SpellError term=reverse ctermfg=DarkRed guifg=Red
149
150    " with HTML, don't mark any errors in e-mail addresses or URLs, and ignore
151    " anything marked in a fix-width font (as being computer code):
152    if HTML
153       syntax case ignore
154       syntax match Normal !\<[[:alnum:]._-]\+@[[:alnum:]._-]\+\.\a\+\>!
155       syntax match Normal
156       \ !\<\(ht\|f\)tp://[-[:alnum:].]\+\a\(/[-_.[:alnum:]/#&=,]*\)\=\>!
157       syntax region Normal start=!<Pre>! end=!</Pre>!
158       syntax region Normal start=!<Code>! end=!</Code>!
159       syntax region Normal start=!<Kbd>! end=!</Kbd>!
160    endif
161 endfunction " HighlightSpellingErrors()
162
163
164 function! AddWordToDictionary()
165 " adds the word under the cursor to the personal dictionary; used for the \sa
166 " operation defined above;
167 " requires the global variable PersonalDict to be defined above, and to contain
168 " the `Ispell' personal dictionary;
169 "
170 " by Smylers  http://www.stripey.com/vim/
171 "
172 " 2000 Apr 30: for `Vim' 5.6
173
174 " get the word under the cursor, including the apostrophe as a word character
175 " to allow for words like "won't", but then ignoring any apostrophes at the
176 " start or end of the word:
177    setlocal iskeyword+='
178    let Word = substitute(expand('<cword>'), "^'\\+", '', '')
179    let Word = substitute(Word, "'\\+$", '', '')
180    setlocal iskeyword-='
181
182    " override any SpellError highlighting that might exist for this word,
183    " `highlighting' it as normal text:
184    execute 'syntax match Normal #\<' . Word . '\>#'
185
186    " remove any final "'s" so that possessive forms don't end up in the
187    " dictionary, then add the word to the dictionary:
188    let Word = substitute(Word, "'s$", '', '')
189    execute '!echo "' . Word . '" >> ' . g:PersonalDict
190 endfunction " AddWordToDictionary()
191
192
193 function! RecodeAndSpellcheck(language)
194    " If the console encoding differs from the file encoding...
195    if strlen(&encoding) && strlen(&fileencoding) && &encoding != &fileencoding
196       " ...save the file encoding...
197       let FileEncoding = &fileencoding
198       " ...and recode to the console encoding
199       execute 'setlocal fileencoding=' . &encoding
200    else
201       let FileEncoding = ''
202    endif
203
204    update
205
206    if strlen(a:language)
207       execute '!ispell -x -d ' . a:language . ' ' . shellescape(expand("%"))
208    else
209       execute '!ispell -x ' . shellescape(expand("%"))
210    endif
211
212    edit %
213
214    if strlen(FileEncoding)
215       " Now recode it back to the saved file encoding
216       execute 'setlocal fileencoding=' . FileEncoding
217       update
218    endif
219 endfunction " RecodeAndSpellcheck()