Vim搜索不覆盖“/”寄存器

4
我想在vimscript搜索时使用斜杆(/),但我不想覆盖"/寄存器。怎么做?
在我的特定示例中,我正在为LaTeX工作的自定义vim文本对象a$上工作,以指定前一个和下一个美元符号($字符,用于界定LaTeX中的数学模式)之间的区域,包括这两个符号。 我遵循此处找到的指南,该指南建议使用vnoremapomap命令,这是一种简单的方法。我想写的是:
vnoremap a$ :<C-U> execute "normal! ?\\$\rvN"<CR>
omap a$ :normal va$<CR>

然而,这种实现存在致命缺陷:"/" 寄存器被覆盖为搜索美元符号字符,清除任何先前的搜索结果,并在尝试使用 "n" 或 "N" 搜索下一个时导致混乱和低效。

我对vimscript相对较新,因此欢迎对编码风格进行评论和挑剔。 - David J
4个回答

4

保存@/。搜索。恢复@/。可能无法将所有内容压缩到映射中,所以建议使用函数代替:

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

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

4

我建议考虑使用keeppatterns命令。

正如:h keeppatterns所说,“执行{command},而不向搜索历史记录中添加任何内容”,它可以帮助您构建映射。


1
/keeppattern结合使用似乎只会将光标移动到包含匹配项的行的开头,并不会跳转到匹配项的开头。它还似乎忽略了当前行上的匹配项。因此,:keepattern /实际上并不像/那样起作用。 - koyae

3

如果 $ 总是在同一行上,那么最好使用 ft 来创建您的自定义文本对象。

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

如果您的文本对象跨越多行,则需要进行某种搜索。以下是一个使用 search() 的示例,它不会更改搜索寄存器。

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

正如@ViVeteran所说,您还可以在使用/或?时使用:keeppatterns,以避免更改搜索注册表和历史记录。
xnoremap :<c-u>execute "keeppatterns normal! ?\\$\<cr>v/\\$"<cr>
onoremap a$ :normal va$<cr>

注意:使用:keeppatterns需要Vim 7.4.083或以上版本。
对于更复杂的自定义文本对象,可以使用vim-textobj-user。您可能需要查看vim-textobj-latex,它使用vim-textobject-user创建了一系列特定于Latex的文本对象。
如需更多帮助,请参见:
:h Operator-pending
:h :map-modes
:h c_CTRL-U
:h search()
:h :keeppatterns

0

我的SearchAsQuickJump插件提供了这个实现。你可以使用正常的搜索(/{pattern}),但是在GVIM中通过<S-CR>而不是<CR>来结束它。这将搜索但保留原始搜索模式。它还具有与内置*#搜索相对应的命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接