Writing Prose in Vim
If you know me at all, you probably know I am a fan of vim. I have written more than a few blog posts on it already.
Most vim users use vim for programming. That is, after all, what most people use plain text editors for. However, since learning vim, I have tried to use it for as much as I can. Everything from emails to blog posts to letters. Of course, programming as well, but certainly not only that.
“Why?”, you might ask. Because it makes my life easier. I have said before that Vim is not as difficult as many vim users would like you to think it is.
Spellcheck
I need a spell check. My spelling is atrocious. This is not helped by the fact that I am dyslexic. Having a decent spell checker is essential if I am writing anything that is going to be read by another human. Incidently, I count future me as another human in this regard.
Vim has a built-in spell check.
set spell
set spelllang=en_gb
How it will look will depend on your colour scheme but in my case it is an underline.
Basic usage consists of the following keyboard shortcuts:
[s
or]s
to move between misspelled wordsz=
to get a list of suggestionszg
to add the current word to your custom dictionary
As with anything in vim, these shortcuts can be changed, although I have never felt the need to.
Vim’s insert completion can be used to look up words in the internal
dictionary as well. To use this, start writing a word and complete it
with ctrl-x ctrl-k
.
This will present you with a list of words that start with what you
have typed. You can select one, as normal, with ctrl-n
and
ctrl-p
.
Finally, on the topic of spell checking, I have added an insert mode mapping that is used to correct the previous misspelled word.
The mapping is as follows:
inoremap <C-l> <c-g>u<Esc>[s1z=`]a<c-g>u
<c-g>u
- break undo sequence (new change)<Esc>
- go into normal mode[s
- go to previous spelling mistake1z=
- change to the top spelling suggestion- `
]
- go to the end of the last changed word a
- enter insert mode<c-g>u
- break undo sequence (new change)
This was shamelessly stolen from Gilles Castel’s excellent blog post on using vim for LaTeX
Undo Points
When programming in vim, a lot of time is spent in both normal mode and insert mode. However, when writing prose, much more time is spent in insert mode. As a result, each undo point tends to be much larger. This can result in the rather annoying behaviour that undoing anything can remove a huge amount of writing.
To minimize this annoyance, I add undo points whenever I type punctuation points.
inoremap ! !<C-g>u
inoremap , ,<C-g>u
inoremap . .<C-g>u
inoremap : :<C-g>u
inoremap ; ;<C-g>u
inoremap ? ?<C-g>u
inoremap ( <C-g>u(
inoremap ) )<C-g>u
The only point I really need to elaborate on here is that for the opening bracket: I add the undo-point before inserting the character. This results in what I consider preferable behaviour whereby a whole bracket group is removed at once when undoing, rather than leaving the opening bracket.
Distraction Free Writing
Distraction free writing seems to be quite a fashionable / desirable feature in a lot of editors at the moment. I have tried and used Goyo and limelight which go some way to reproducing the distraction free environment of many other editors. However, I no longer use them. Both worked well, but vim doesn’t have that many distractions without them. When I am writing, I open vim in a full screen terminal. I don’t even have a clock visible. Being able to highlight the paragraph I am currently working on or putting the text in the middle of the screen wasn’t worth it for me.
Proselint
Proselint, as the name suggests, is a linter for prose. It points out areas where my writing could be better. To use it with vim, I have the following autofunction:
function! mine#functions#proselint() abort
let oldmakeprg = &l:makeprg
" set new value of makeprg and call the function
set makeprg=proselint\ %
make
copen
" set makeprg back to old value
let &l:makeprg = oldmakeprg
endfunction
and a mapping:
nnoremap <leader>p :call mine#functions#proselint()<CR>
This allows me to fill the quickfix list with a list of suggestions from proselint.
LanguageTool
LanguageTool is similar in concept to Proselint although seems to have a lot more checks under its hood. It can be intergrated into vim in a similar way to Proselint, with an autofunction.
function! mine#functions#languagetool() abort
let oldmakeprg = &l:makeprg
let olderrformat = &l:errorformat
" set new value of makeprg and call the function
set makeprg=languagetool\ -l\ en-GB\ %
let &l:errorformat =
\ '%-GPicked up _JAVA_OPTIONS: %.%#,' .
\ '%-GExpected text language: %.%#,' .
\ '%-PWorking on %f...,' .
\ '%-I%.%# [main] DEBUG %.%#,' .
\ '%+IUsing %.%# for file %.%#,' .
\ '%I%\d%\+.) Line %l\, column %c\, Rule ID: %m,' .
\ '%-CMessage%m,' .
\ '%-CSuggestion%m,' .
\ '%-CMore info%m,' .
\ '%-C%\s%#^%\+%\s%#,' .
\ '%-C%.%#,' .
\ '%-Z%\s%#,' .
\ '%-Q,' .
\ '%-GTime: %.%#'
make
copen
" set makeprg back to old value
let &l:makeprg = oldmakeprg
let &l:makeprg = olderrformat
endfunction
You will notice that this is slightly longer because the error format used by Proselint is compatible with Vim’s default. LanguageTool’s is not.