Improving My Neovim Spellcheck Workflow

Spellcheck in Neovim is a feature I use a bit and I wanted to improve my workflow.

The base spelling suggestions prompt isn't too ergonomic when you type z= on a word:

I use the telescope plugin as a universal fuzzy finder which makes this a bit more user friendly:

Still, I have to first notice the mistake, which Neovim underlines. I might have typed some more so I hit b several times to return. I can do z=, quickly fix the word, and assuming I was still writing something, I need to move the cursor back to where it was (often just A). But this is all an inconvenience that distracts from the flow.

Spellcheck in Neovim

First, spellchecking needs to be enabled:

vim.o.spell = true
vim.opt.spelllang = { 'en_us' }

There are just a few keymaps to use:

[s and ]s - jump to previous/next incorrect word

zg - mark a word as correct - adds to a wordlist in config folder

zw - mark a word as wrong - adds to a wordlist in config folder

z= - show a spelling suggestions prompt

As a single mapping

Neovim already has a keymap to go to a previous mistake: [s. Let's combine steps and have one mapping to go back to the mistake and open the prompt. While you can do z= on a correct word, I don't so I'm fine with overwriting the map:

vim.keymap.set('n', 'z=', '[sz=', { noremap = true })

With telescope:

vim.keymap.set('n', 'z=', function()
-- back to spelling mistake then show prompt
vim.cmd.normal('[s')
telescope.spell_suggest(themes.get_dropdown())
end)

Auto-accept the first suggestion

I almost always accept the first suggestion, and researching this post made me realize that was already an option if you use a count: 1z= chooses the first suggestion even without showing you them. So let's set z+ to ergonomically do that by finding the mistake, fixing it, and jumping back to previous cursor position (Ctrl+o). (Note: z+ is an existing Neovim mapping, but not something I care about losing.)

vim.keymap.set('n', 'z+', '[s1z=<C-o>', { noremap = true })
-- noremap used here to refer to call the original z=, not my custom mapping

And in insert mode

Now let's do that in insert mode so I can catch it with one command while typing instead of hitting <esc>, z+, and a to go back to insert mode:

vim.keymap.set('i', '<C-z>', '<C-o>:normal z+<CR>')

Let's break it down:

Ctrl+z is unused in insert mode so it's free to be used. (In normal mode, it suspends Neovim to the background, like any other Unix process.)

Ctrl+o in insert mode lets you run a normal mode and resumes insert mode when finished.

I type : to start typing a command.

norm[al] z+ executes the z+ keymap, don't forget to hit carriage return (<CR>) aka enter.

Putting it all together

I'll keep my overridden z= mapping above.

I added (normal mode) z+ to go back and fix using the first suggestion.

I added (insert mode) Ctrl+z to fix the mistake without interrupting my current train of thought. I imagine this will become a frequently used command!

After a bit of use I even swapped the mappings so z= is the autofix as that's easier to type and I use it more than the prompt. I'll use this flow for a bit and package it up as a plugin if the spellcheck flow feels like it's in a good place.