# Make conditional imap to text being enclosed in certain characters

How can I create mappings that work only if the cursor is enclosed by certain characters?

As an example, I want to map ja to \alpha if the cursor is enclosed by $$ or by  so as to make This jar has an ja engraved on it.  be remapped to This jar has an \alpha engraved on it.  instead of This \alphar has an \alpha engraved on it.  So, how can I ask vim to check if the cursor is enclosed by $$'s and 's?

An immediate complication that I can think of is the following:

The jar has an $ja$ engraved on it (note: $ja$ is a greek character).


That is, the check should work just like vim does for checking unclosed parentheses, where there may be several closed ones back too. (Or like LaTeX for checking mathmode). This would be done only on the current line, for scalability.

Here is a scheme of how I would do it for  (if only I knew how to actually check these using vim syntax):

1. Take position of cursor;
2. Scan to the left for the number of $'s; 3. Do the same for the right; 4. If these are even, work as if in normal text (e.g. A jar becomes A jar) 5. If these are odd, do the mappings (e.g. A jar becomes A \alphar) For  I think it could be done in the same way as a check for balanced paratheses... Since, this question is asked having LaTeX in mind, is there a shortcut when using vim-latex, vim-tex, or other TeX plugins for vim? ## 1 Answer This is actually a complicated matter. $...$ is a difficult construct to parse, because it has no clear beginning or end. That is, in math here?$ or math here? $math here?, how do you know which region is really a math region? You need to search further back to know. However, there are some possibilities. In particular, I would take advantage of the fact that there is already a good syntax file for LaTeX that detects these inner match structures. Thus, you can check if you are inside a math environment by looking at the syntax groups. I've implemented this in vimtex. The solution is basically as follows: imap <silent><expr> ja MyFunc('ja', '\alpha') function! MyFunc(lhs, rhs) abort return s:is_math() ? a:rhs : a:lhs endfunction function! s:is_math() abort return match(map(synstack(line('.'), max([col('.') - 1, 1])), \ 'synIDattr(v:val, ''name'')'), '^texMathZone[A-Z]S\?$') >= 0
endfunction


If you want to use vimtex directly, than you can read :help vimtex-imaps. There are already a bunch of such mappings defined by default. See VIMTEX/autoload/vimtex.vim for the complete list.

You may also add your own, custom maps, see :help vimtex#imaps#add_map.

• Thank you so much! It worked like a charm! (Also, you convinced me to switch from latex-suite to vimtex. Really, thank you!)
– Théo
Dec 2 '18 at 18:40
• No problem, happy to help :) Dec 3 '18 at 7:57