Use fzf to show VIM spelling suggestions, and override the built in z=
shortcut
exe 'normal! "_ciw'.a:word
endfunction
)
let suggestions = spellsuggest(expand("<cword>"))
return fzf#run({'source': suggestions, 'sink': function("FzfSpellSink"), 'down': 10 })
endfunction
nnoremap z= :call FzfSpell()<CR> word)
Recently I was looking to add spell-checking to VIM and came across this great ThoughtBot article, Vim Spell-Checking that got me started.
This article showed me how to turn on spellchecking, and also to turn it on for specific files. Here are the snippets from the .vimrc
that are directly inspired from this blog post.
autocmd BufRead,BufNewFile *.md setlocal spell spelllang=en_us
autocmd FileType gitcommit setlocal spell spelllang=en_us
set complete+=kspell
This served me well for quite awhile, but when I ran across misspelled words, it often left me looking for a better way to replace them.
VIM has a built in solution to this in the form of the z=
keyboard shortcut. This takes the current word under cursor and shows spelling suggestions, where selecting a selection will replace the current word. This is the functionality I wanted to keep, but I didn't love the interface that the suggestions appeared in. They take up the entire VIM screen and force you to pick by entering the number corresponding to the word you would like. I am a big fan of fzf, and I wanted to use this for spelling suggestions!
The first thing I needed was a list of the spelling suggestions for the word under the current cursor. Getting the current word is simple enough with expand('<cword>')
so now I just needed to get the spelling suggestions for it.
After a bit of digging [^1] I found the VIM function spellsuggest
. This function takes the word we want suggestions for as its first arguments. It also takes an optional second and third argument, which we are not currently using. The second argument is the number of suggestions to return, the default is 25. The third argument is a flag for whether we should filter to only capitalized words.
spellsuggest(expand('<cword>'))
So I could now use the above command to get a VIM list of spelling suggestions. Next step was to get fzf to let me select an option from this list.
The fzf repo has a readme that details how to use fzf in VIM. I was mostly interested in how to use the fzf#run
function, which is the main function for calling into fzf. This can take a VIM list as input, so it fits really nicely with the list of spelling suggestions we already generated. We pass this is as the source
to fzf#run
. The other important option is sink
which tells fzf what to do after we have selected a suggestion. Now its time to replace the word under the cursor with our suggestion! One of the accepted types for sink
is a VIM function reference so I needed another function to call as a callback, which will responsible for actually replacing the word under the cursor. So far we have the following
let suggestions = spellsuggest(expand("<cword>"))
return fzf#run({'source': suggestions, 'sink': function("FzfSpellSink"), 'down': 10 })
endfunction )
For this we can use the VIM command ciw
to change the current word to what we selected. To execute that from vimscript we use exe
and normal!
giving us the following. This uses the normal mode ciw
and sends the old value to the black hole register "_
, it then inserts the new word.
exe 'normal! "_ciw'.a:word
endfunction word)
The last thing we need is a keyboard shortcut, so I can access this quickly. I want to use this instead of the default z=
behavior so I decided to just remap that shortcut
nnoremap z= :call FzfSpell()<CR>
And finally putting it all together we have... :drumroll:
exe 'normal! "_ciw'.a:word
endfunction
)
let suggestions = spellsuggest(expand("<cword>"))
return fzf#run({'source': suggestions, 'sink': function("FzfSpellSink"), 'down': 10 })
endfunction
nnoremap z= :call FzfSpell()<CR> word)
My weekly newsletter tailored at developers who are eager to grow with me!
Every week will be unique, but expect topics focusing around Web Development and Rust