Vim search without overwriting "/ register

Viewed 578

I would like to use a slash (/) for a search during a vimscript, but I don't want to overwrite the "/ register. How do I do this?

In my particular example, I am working on a custom vim text object for LaTeX, a$, to specify the region between and including the previous and next dollar signs ($ characters, which delimit math mode in LaTeX). I'm following a guide found here which suggests using a vnoremap and an omap command, which is a simple enough approach. What I would like to write is:

vnoremap a$ :<C-U> execute "normal! ?\\$\rvN"<CR>
omap a$ :normal va$<CR>

However, this implementation has a fatal flaw: the "/ register becomes overwritten with the search for the dollar sign character, clearing any previous search and causing confusion and inefficiencies when trying to use n or N next.

4 Answers

Save @/. Search. Restore @/. You might not be able to squeeze all that into a mapping so I'd recommend a function instead:

function! VisualAroundDollar()
    let search = @/
    execute "normal! ?\\$\rvN"
    let @/ = search
endfunction

vnoremap a$ :<C-U>call VisualAroundDollar()<CR>
omap a$ :normal va$<CR>

May I suggest to consider the command keeppatterns

As :h keeppatterns says "Execute {command}, without adding anything to the search history" it may help you to build you mapping

If $ are always on the same line then it is often best to use f & t to make your custom text-objects.

xnoremap a$ :<c-u>normal! F$vf$"<cr>
onoremap a$ :normal va$<cr>

If your text-object goes over multiple lines then you need to do some kind of searching. Here is an example using search() which does not change the search register.

xnoremap a$ :<c-u>call search('\$', 'bcW')<cr>m<:call search('\$', 'W')<cr>m>gv
onoremap a$ :normal va$<cr>

As @ViVeteran stated you can also use :keeppatterns with / or ? to avoid changes to the search register and history.

xnoremap :<c-u>execute "keeppatterns normal! ?\\$\<cr>v/\\$"<cr>
onoremap a$ :normal va$<cr>

Note: :keeppatterns requires Vim 7.4.083+

For more complicated custom text-objects there is vim-textobj-user. You may want to look into vim-textobj-latex which use vim-textobject-user to create an assortment of Latex specific text-objects.

For more help see:

:h Operator-pending
:h :map-modes
:h c_CTRL-U
:h search()
:h :keeppatterns

My SearchAsQuickJump plugin provides an implementation of this. You can use the normal search (/{pattern}), but conclude it (in GVIM) via <S-CR> instead of <CR>. That will search but keep the original search pattern. It also has commands that correspond to the built-in * and # searches.

Related