LaTeX and Vim Part 2

By John Lenz. May 9, 2013.

This is a continuation of my last post, explaining the plugins and configuration I use for Vim and LaTeX.

Forward Search

Update: After writing this post, I enhanced the forward search and describe it in this post.

Forward search is the ability to open/change the page of the PDF editor to match the current cursor location inside Vim. At the moment, my forward search is limited to opening the PDF viewer to the page containing a specific LaTeX label. A more detailed forward search is possible (google search "Vim Evince Forward Search") but all the results from that google search didn't work for me because they use the Evince dbus API and the dbus API has changed since those were posted, breaking the code.

Instead, I wrote a very simple forward search that avoids the dbus API and instead uses the command line. It has a better chance of continuing to work in the future whereas the more complicated methods with the dbus API will require effort to be kept up to date. Here is the code I wrote; it is located at ~/academic/tools/ftplugin/tex.vim.

"Load PDF to the page containing label
function! LoadEvinceByLabel(l)
    for f in split(glob("*.aux"))
        let label = system('grep "^.newlabel{' . a:l . '" ' . f)
        let page = matchstr(label, '.\{}{\zs.*\ze}}')
        if ! empty(page)
            call OpenPDF(substitute(f, "aux$", "pdf", ""), page)
com! -nargs=1 -complete=tag Pdf call LoadEvinceByLabel("<args>")

"Load PDF to the page containing the nearest previous label to the cursor
function! EvinceNearestLabel()
    let line = search("\\label{", "bnW")
    if line > 0
        let m = matchstr(getline(line), '\\label{\zs[^}]*\ze}')
        if empty(m)
            echomsg "No label between here and start of file"
            call LoadEvinceByLabel(m)
map <buffer> <LocalLeader>e :call EvinceNearestLabel()<CR>

function! OpenPDF(file,page)
    exec 'silent ! evince --page-label=' . a:page . ' ' . a:file . ' > /dev/null 2>&1 &'

To use it, you can either use ":Pdf <label>" with tab completion if you have set up the tag generation, or you can use \e to have Vim search earlier in the file from the cursor for a label and open the PDF to the page containing that label. I should perhaps add the ability to search up and down and pick the nearer label. To quickly navigate around, I use Ctrl-P on tags so I can, with a few keystrokes, jump in Vim to the label and then open evince.

There is code for the gedit forward search plugin synctex which seems to keep up to date with the changing evince dbus API, so perhaps it could be used as the basis for a forward search Vim plugin.

Snippets and Folding

I didn't like the way the Vim-LaTeX suite plugin did folding nor any of the plugins I looked at. Instead, I decided to use marker folding (:help fold-marker). For marker folding to work, we need to insert {{{ and }}} into the files which is easy to do with the right snippets. For snippets, I use ultisnips but I rewrote my own snippets instead of using the ones built in to ultisnips. For example, my section and subsection snippets are

snippet sec
\section{${1:section name}} % {{{1

snippet sub
\subsection{${1:subsection name}} % {{{2


Note the presence of markers. Similarly, I have markers for various begin/end snippets, some of them folded, some of them not. For example,

snippet proof
\begin{proof} % {{{
\end{proof} % }}}


Vim has builtin TeX indenting but there are a few settings you can change to control the indent. The settings are listed in the comments at the top of /usr/share/vim/vim73/indent/tex.vim. The indenting works well, but I am still only 95% happy with the indenting. I might look at fixing the last few corner cases, mostly related to indenting within an equation or align block.

Final Thoughts

That is basically my vim + TeX environment. I have a few more settings configured like textwidth, indent, some shorthand maps for tag completion, and this tip for rewrapping paragraphs.

The only major problem I have is that LaTeX compiler output sucks badly. Rubber does a decent job cleaning up the output so that a vim errorformat can jump between errors, but still there are a lot of errors that don't specify a line number, sometimes errors only give a page number, sometimes give no mark where they occur at all. Especially things like mismatched braces which every other compiler seems to provide helpful error messages, TeX just tells you some problem is in a paragraph. The excellent plugin syntastic has support for displaying error messages if they were generated, and syntastic does use lacheck and/or chktex. But both of those tools are limited and both are no longer developed. I feel that a better checking tool is needed, one that provides nice error messages and warnings. I started work on just such a tool called latex-candle but am currently working on other things. Perhaps I will come back to it in the future though, or would help on another project if one existed.