Notes on Vim

Stripping TeX commands

Consider the following TeX snippet:

\hl{this is \emph{emphasized} and highlighted}

Now, suppose you want to remove the outer highlight, i.e., \hl{ ... }.1 One way to accomplish this in Vim is to use a rudimentary substitute command :%s/\\hl{\(.*\)}/\1/g, which would do the trick since Vim regular expressions are greedy. But this will not handle the following snippet

\hl{this is \emph{emphasized}} and \hl{highlighted}

which would be turned into

this is \emph{emphasized}} and \hl{highlighted

which is obviously not what we want. The issue is that you need to match braces and conventional regular expressions are not suited for such a task. A possible alternative is to use Vim macros, but that can also get clunky. A better method, however, is to programmatically do the commands that you would record into a macro, by writing a function instead. For my purposes, the below function (and the associated command) seems to work well and it strips the \hl{ ... } command without issues.

function! s:texstrip(cmd)
  let winview = winsaveview()
  let i = 1 " to prevent potential infinite loops
  while search('\V\\' . a:cmd . '{', 'w') && i <= 1000
    let m = getpos('.')
    " Move to open brace, find matching brace, and then cut
    " to black hole register.
    normal! f{%"_x
    " Move back and delete to open brace.
    call cursor(m[1], m[2])
    normal! "_df{
    let i = i + 1
  endwhile
  call winrestview(winview)
endfunction

command! -nargs=1 TeXStrip silent call s:texstrip(<f-args>)

Put this in ~/.vim/after/ftplugin/tex.vim. Using the TeXStrip command, \hl{ ... } can now be removed via :TeXStrip hl. The general usage is :TeXStrip {pattern}, where {pattern} is treated as a “very nomagic” pattern.

Last updated: 2022-04-22 12:00 EDT