7

I use Vim to edit LaTeX files frequently. I want to use % to jump between matching $ which can be used to delimit where mathematical expressions are written.

I have tried using matchit and, separately, I have tried using a filetype.vim (tex.vim) file to add a match to the matchpairs variable (au FileType tex setmps+=$:$). I have managed to get both attempts to jump from the $. However, the match that is found is for a different delimiter.

For example, considering the string $ { test text } $, placing my cursor over the first $ and pressing % would jump me to the closing }, not the last $. Continued use of % jumps me between { and }. Thus, I am stuck inside the match that I want to consider.

Does anyone know how I might accomplish a jump from the first $ to the last $?

1
  • If both are on the same line, you could just type f$, and then ; and , to jump between them.
    – Wildcard
    Feb 15, 2016 at 7:42

3 Answers 3

6

What you ask is possible, but the solution is nontrivial. Both LaTeX-Box and vimtex has implemented solutions for this, see here:

These functions are run by autocommands whenever the cursor is moved, see here (LaTeX-Box) and here (vimtex). The original matchparen plugin is disabled, and the LaTeX-specific function, e.g. s:highlight_matching_pair, is enabled as a custom matchparen-plugin. Note that both these functions also enable matching of other LaTeX-delimiters such as begin/end pairs and pairs like \left(..\right).

Note: The links above are linked to line numbers in evolving codes. These line numbers might change in the future. The function names will probably stay the same.

Note: Other LaTeX-plugins might also implement this feature.

Disclaimer: I'm the author of vimtex.

2
  • Thanks, Karl, for your explanation. I understand, now, that I won't be adding a couple lines to my .vimrc to implement this functionality. I use vim-latex as my current vim plugin for editing LaTeX files. I'm considering forking vim-latex to improve it. If I do this, I might introduce something like your s:highlight_matching_pair or LaTeX-Box's s:FindMatchingPair. I see that both plugins require a separate logic branch (if statement) to process if the delimiter being matched is a '$', or not. It's special. Jun 8, 2015 at 22:34
  • Personally I don't recommend forking vim-latex (aka LaTeX-Suite), instead I would suggest you open a pull request here. Personally I don't like vim-latex, mostly because it is huge and difficult to improve and customize. Jun 9, 2015 at 6:29
3

Your $ match is ignored, % searches forward for the first character in a pair that it knows about: so it finds { and then the matching }, and moves between them.

From :h mps:

Only character pairs are allowed that are different,
thus you cannot jump between two double quotes.

One solution would be: to use the 'matchit' plugin (which allows for regular expressions as pairs, but has the same start != end delimiter) AND use the LaTeX math delimiters \( \), which are different. Or, define two new TeX different commands for start & end inline math environment, that both resolve to $, and use them as pairs.

So, you can do in your vimrc:

runtime! macros/matchit.vim

And, for TeX files (e.g. in a function called from a BufEnter autocmd):

let b:match_words = '\\(:\\)'

If you have to use the $ sign, you can cheat a little and use this:

let b:match_words = '\s\$:\$\s'

... which will match a $ preceded by space as start delimiter with a $ followed by a space as end delimiter. But then you'll have to be consistent inside your formulas and use no space after the start delimiter, or before the end one. E.g.:

 ␣$\cos (2\theta) = \cos^2 \theta - \sin^2 \theta$␣ 
5
  • Vim already knows which $ characters are opening and which are closing because it highlights math segments. Could the information used by highlighting be leveraged for that improved % command? Jun 8, 2015 at 21:53
  • If you open $VIMRUNTIME/syntax/tex.vim and search for \$s (heh), you'll see comments like this: «The $..$ and $$..$$ make for impossible sync patterns (one can't tell if a "$$" starts or stops a math zone by itself) The following grouptheres coupled with minlines above help improve the odds of good syncing.» and «4. There is no match-syncing for $...$ and $$...$$; hence large equation blocks constructed that way may exhibit syncing problems (there's no difference between begin/end patterns)». Maybe if you use text objects instead, e.g.: github.com/gibiansky/vim-latex-objects
    – VanLaser
    Jun 8, 2015 at 22:24
  • To reuse existing syntax highlighting, but still with text-objects, you also have: github.com/kana/vim-textobj-syntax, which defines a textobj-syntax-i as "the syntax highlighted item under the cursor". Then, for example, you can visually select the $...$ as math object, and if you hit o, move cursor to the other end of the visual selection. But still doesn't answer your suggestion of implementing % from syntax highlight rules ... I would like to see a vim guru coming up with some idea.
    – VanLaser
    Jun 8, 2015 at 22:31
  • Both vimtex and LaTeX-Box use the syntax group to determine the boundaries of $...$ as suggested by @Gilles. Jun 9, 2015 at 6:31
  • Another reason to use vimtex, then :) Thanks for the info.
    – VanLaser
    Jun 9, 2015 at 8:41
2

Add

runtime! macros/matchit.vim

into ~/.vimrc and into ~/.vim/after/ftplugin/tex.vim the lines

let b:match_words = &l:matchpairs .
  \ ',' . '\(^\|[ (]\)\@<=\$\$\?' . ':' . '\$\?\$\($\|[ ).\,;\:?!\-]\)' .
  \ ',' . '\(' . ':' . '\)' .
  \ ',' . '\[' . ':' . '\]' .
  \ ',' . '\(^\s*\)\@<=\\begin{\w\+\*\?}' . ':' . '\(^\s*\)\@<=\\end{\w\+\*\?}'

This lets you jump between all TeX environment delimiters by % (but isn't yet entirely robust).

1
  • Thanks, I'm actually using the vimtex plugin which is in active development and provides a lot of nice TeX features. You might check it out. Feb 23, 2016 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.