Vim and LaTeX


Vim and LaTeX

LaTeX is the de facto standard tool for writing academic papers. When working with groups I generally find myself using Share LaTeX. Share LaTeX is a great way to collaborate Google Docs-style one a LaTeX document, and it has a very forgiving compiler that in general seems to get things right. As is the case with so many other things, however: editing LaTeX is better with Vim.

Until recently I’d been using Latex-Box for some pretty nifty vim functionality. Recently I began looking for a way to do things like autocomplete citations. In my search for how to do this I came across an alternative plugin called vimtex, made by one of the same people behind LaTeX-Box.

Special Functionality

Overall vimtex is a straight upgrade over LaTeX-Box. Here is some of the functionality I’ve been enjoying.

Linting and syntax checking runs on save. It will include helpful resolution suggestions, which is a huge improvement even over Share LateX, which seems to prefer just swallowing errors.

The document can be compiled with <leader>ll. In LaTeX-Box this command just issued a compile command that would hang the editor until it completed. With vimtex it starts “continuous mode”, which means that on every save the document is compiled asynchronously. If you open the resulting PDF with a browser like Skim and enable auto-reloading, you can watch your document compile on every save. Homebrew users can install Skim with brew cask install skim.

A table of contents showing sections and subsections is shown with <leader>lt. The table of contents can be navigated using j and k and jumped to by pressing enter.

Environments (like begin{enumerate}) can be closed using ]]. In LaTeX-Box I had to add special macro that applied only to .tex files for this to work. Not so with vimtex.

General Editing

Several other changes make editing with vimtex more enjoyable.

I like wrapping my text at 79 characters. This is mostly due to the fact that I started putting a text column alert at 80 rather than 81, and as a consequence I’d been wrapping all my files to 79 characters. It just so happens this also follows the official Python guidelines, so I ended up leaving it at 79 rather than fixing it. To get text to autowrap at 79 characters in vim I have the following my .vimrc:

set wrap
set textwidth=79

With that addition I can type normally and vim wraps the text for me, letting me ignore line breaks. Before that I would try and guess when a word would make a line too long. It was miserable.

A companion operator to this is gw. gw re-wraps text and leaves it where it was when the command was issued (as opposed to gq). After I edit a paragraph I frequently fire off a gwap, which will re-wrap the paragraph containing my cursor. This lets me edit with impunity and keep the pretty wrapping that makes the source legible. One downside of this is that git frequently will show that I’ve changed a whole paragraph when I’ve really deleted or added a word and re-wrapped. This doesn’t bother me too much, however, as it’s hard to see word-based diffs when shown at the line level anyways.

Another nicety is using YouCompleteMe for completion. Setting up YCM can be tricky, but after it’s in place it is very nice (check the README for good instructions). YCM loads by default whenever I start vim. It can be annoying when typing text, as it suggests something for every word, which I find distracting. I’ve added these lines to my .vimrc, which let me use <leader>y to turn off YCM auto completing every single word:

" Turn off YCM
nnoremap <leader>y :let g:ycm_auto_trigger=0<CR>
" Turn on YCM
nnoremap <leader>Y :let g:ycm_auto_trigger=1<CR>

Generally when I open a .tex file I first press <leader>y to turn off YCM. If I need it back, it’s a simple <leader>Y.

The real power of YCM and vimtex comes from completing things like \label and \cite commands. With YCM plugged in correctly, I’m able to type \cite{designing internet, press <C-space> and have YCM search my .bib file to suggest completions based on title and author. This is a huge time saver and keeps me from having to switch back and forth between different files to add citations. The only thing needed to get this to work is adding a few lines to your .vimrc indicating what contextual triggers should trigger YCM. The vimtex documentation includes this with Help command: :h vimtex-complete-youcompleteme.

This reports that you should add this to your .vimrc:

if !exists('g:ycm_semantic_triggers')
  let g:ycm_semantic_triggers = {}
endif
let g:ycm_semantic_triggers.tex = [
      \ 're!\\[A-Za-z]*cite[A-Za-z]*(\[[^]]*\]){0,2}{[^}]*',
      \ 're!\\[A-Za-z]*ref({[^}]*|range{([^,{}]*(}{)?))',
      \ 're!\\hyperref\[[^]]*',
      \ 're!\\includegraphics\*?(\[[^]]*\]){0,2}{[^}]*',
      \ 're!\\(include(only)?|input){[^}]*',
      \ 're!\\\a*(gls|Gls|GLS)(pl)?\a*(\s*\[[^]]*\]){0,2}\s*\{[^}]*',
      \ 're!\\includepdf(\s*\[[^]]*\])?\s*\{[^}]*',
      \ 're!\\includestandalone(\s*\[[^]]*\])?\s*\{[^}]*',
      \ ]

With this you can use <C-space> to complete things like citations. Everything that can be autocompleted is shown in the above command if you unpack it.


comments powered by Disqus