Vim Tips Wiki
Advertisement
Tip 1173 Printable Monobook Previous Next

created March 16, 2006 · complexity intermediate · author Ben Staniford · version 5.7


A little while ago, I tried out all the spelling plug-ins for Vim because I was doing a bit of a project and needed to make sure it was all beautifully spelled. One function that I found really lacking in the various spelling plug-ins was the ability to make suggestions on the current word. Some of them allowed this facility but there were restrictions, such as only being able to use it in graphical mode and only being able to use it on certain types of files. I wanted something that would work anywhere, whether in some code, in a text doc and that would work in console mode. I also wanted to see how easily I could in-line some Perl into a Vim script to perform some function on it. The answer to that was that it's not impossible, but it's a bit ugly!

Here's the function I created.

" F7 Will give some spelling suggestions for the current word in any mode
nmap <F7> \ss
vmap <F7> <C-C> \ss
omap <F7> \ss
map! <F7> <C-C> \ss
noremap <silent> \ss :call SuggestWord()<CR>

"Make some spelling suggestions for the current word, and allow you to change it for the word you prefer
"Requires ispell and perl
"By Ben Staniford
function! SuggestWord ()
  let rw = tempname()
  let oldspelling = expand("<cword>")
  "Run ispell on the word under the cursor and prompt us for a choice, then save it to a temp file
  exe '!echo -n '.oldspelling.' | ispell -a -S | perl -e '."\x27".'print "\n\n\n";'.
        \ 'while(<>) {if(/.*:\s(.*$)/){$m=1;@a=split ", ",$1;print "Suggestions: [CTL-C to abort]\n";'.
        \ 'for (@a) {print ++$i.")$_ "} print "\n>"; open (I, "/dev/tty"); $b=<I>; open(RW,">'.rw.'");'.
        \ 'print RW "$a[$b-1]";}}if($m\!=1){print "No Suggestions\n"}'."\x27"
  "If the user selected a word and it was saved, read it now
  if filereadable(rw)
    exe 'read ! cat '.rw
    exe "normal \"adw"
    exe "normal ddk"
    exe "normal /".oldspelling."\<CR>"
    exe "normal cw"
    "Print the word slightly differently if we're at the beginning of a line
    if (wincol() == 1)
      exe "normal \"aP"
    else
      exe "normal \"ap"
    endif
  endif
endfunction "SuggestWord()

Comments

 TO DO 
Update tip for Vim 7. Spell checking is now built-in.

And yet aspell has very good heuristics regarding alternatives suggestion.
--Luc Hermitte 01:36, 19 April 2008 (UTC)

Here's a version that does not require Perl:

nnoremap <silent><F2> :cal SpellSuggest()<CR>
function! SpellSuggest()
  let s = substitute(system("echo ".expand("<cword>")." | aspell -a -W2 | grep '^&'"), "^.*:\\s\\(.*\\)\\n", "\\1,", "")
  if s != ""
    let slength = strlen(s)
    let end = 0
    let i = 0
    while end != slength
      let i = i + 1
      let w = matchstr(s, "^\\%(.\\{-}\\zs[^ ,]\\+\\ze,\\)\\{".i."}")
      echon "(".i.")".w." "
      let end = matchend(s, w.",")
    endwhile
    echo ""
    let c = input("Replace with: ")
    if c =~ "^[1-9]\\d*$" && c > 0 && c <= i
      execute "normal! ciw".matchstr(s, "^\\%(.\\{-}\\zs[^ ,]\\+\\ze,\\)\\{".c."}")
    endif
  else
    echo "No suggestions"
  endif
endfunction

Advertisement