Subversive.vim
Subversive提供了两种新的操作动作,使得快速替换变得非常简单。它不包含任何默认映射,在您添加自己的映射之前不会产生任何效果。
如果您更喜欢观看视频解释而不是阅读以下文本,也可以点击这里。
替换动作
示例配置:
" s 表示替换
nmap s <plug>(SubversiveSubstitute)
nmap ss <plug>(SubversiveSubstituteLine)
nmap S <plug>(SubversiveSubstituteToEndOfLine)
请注意,在这种情况下,您将覆盖更改字符键 s
,因此您必须使用较长的形式 cl
。
添加这些映射后,您可以执行 s<动作>
来用默认寄存器(或指定的寄存器)的内容替换由动作提供的文本对象。例如,您可以执行 siw
来用当前复制的内容替换光标下的当前单词,或执行 sip
来替换段落等。
范围替换动作
Subversive提供的另一个有趣的操作允许通过使用多个连续的动作来同时指定要替换的文本和应用更改的行范围。
示例配置:
nmap <leader>s <plug>(SubversiveSubstituteRange)
xmap <leader>s <plug>(SubversiveSubstituteRange)
nmap <leader>ss <plug>(SubversiveSubstituteWordRange)
添加此映射后,如果您执行 <leader>s<动作1><动作2>
,然后在状态栏的提示中输入一些文本,那么由 动作1
给出的文本将被我们在提示中输入的文本替换,替换范围为 动作2
提供的每一行。另外,我们也可以在可视模式下选择 动作1
,然后按 <leader>s<动作2>
来达到相同的效果。
这可以非常强大。例如,您可以执行 <leader>siwip
来替换光标下当前单词在光标所在段落中的所有实例。或执行 <leader>sl_
来替换当前行上光标下字符的所有实例。
<leader>ss
映射用作替换光标下当前单词的快捷方式。例如,这允许您执行 <leader>ssip
来替换当前段落中光标下的单词。请注意,这匹配的是完整单词,因此与 <leader>siwip
不同(后者不要求每个匹配都有单词边界)。
让我们看看它的实际效果:
在这个 gif 中,我们首先通过执行 <leader>ssom
然后在提示中输入 bar
来重命名本地 foo
参数(注意 om
是一个自定义动作,表示 "outer c# method",不是由这个插件提供的)。另外请注意,因为我们使用的是 <leader>ss
,所以 _foos
文本不受影响,因为它不匹配完整的单词。在这种情况下这很有用,因为我们只想在函数内重命名参数。
之后我们切换到可视模式,选择 _foos
中的 foo
部分,然后执行 <leader>sie
,再次在提示中输入 bar
。ie
再次是一个自定义动作,表示 entire buffer
(参见下一节了解详情)。
之后我们移动到 AddFoo
中的 Foo
部分,执行 <leader>seie
并再次输入 Bar
。然后最后对全大写的 FOOS
做同样的操作。
请注意,如果您使用的是 neovim,您可以启用 inccommand
选项,以在输入替换内容时获得实时预览(相当于将 g:subversivePromptWithActualCommand
设置为 1
)。
还要注意,这个动作是可重复的。如果您在一个段落中运行 <leader>siwip
,然后移动到另一个段落,再按 .
,那么相同的替换将应用于光标下的新段落。
自定义文本对象
请注意,要充分利用这些映射,除了内置的文本对象(如当前段落 ip
、当前句子 is
或当前行 _
)之外,添加自定义文本对象会很有帮助。自定义文本对象,如当前缩进级别、当前方法、当前类、整个缓冲区、当前滚动页面等,都可以在这里提供很大帮助。
例如,对 Subversive 非常有用的几个简单动作是:
" ie = 整个缓冲区内部
onoremap ie :exec "normal! ggVG"<cr>
" iv = 缓冲区中当前可见的文本
onoremap iv :exec "normal! HVL"<cr>
还有其他提供大量自定义文本对象的插件,我建议您看一看。
确认每个替换
对于许多替换,您可以依赖高亮预览来了解正在替换的内容。但如果您要在整个文件中进行较大的替换,您可能想确认每一个替换。您可以使用以下映射来实现这一点:
nmap <leader>cs <plug>(SubversiveSubstituteRangeConfirm)
xmap <leader>cs <plug>(SubversiveSubstituteRangeConfirm)
nmap <leader>css <plug>(SubversiveSubstituteWordRangeConfirm)
这些映射的工作方式与上面的 <leader>s
映射相同,只是会逐个确认每个替换。
问题
-
如果我不想使用提示,而想直接用寄存器的值替换怎么办?
如果您为上述任何替换动作提供一个显式的寄存器,它将不会提示,而是直接使用给定寄存器的内容。例如,
"a<leader>siwip
将立即用寄存器a
的内容替换当前段落中光标下当前单词的所有实例。如果这还不够,您还可以使用以下插件代替:
nmap <leader>s <plug>(SubversiveSubstituteRangeNoPrompt) xmap <leader>s <plug>(SubversiveSubstituteRangeNoPrompt) nmap <leader>ss <plug>(SubversiveSubstituteWordRangeNoPrompt)
这些插件的工作方式与之前的插件完全相同,只是不会提示,而是使用默认寄存器。
-
如果我只想删除而不是替换怎么办?
您可以通过将黑洞寄存器传递给范围替换命令之一来实现这一点。例如:
"_<leader>siwip
或"_<leader>csiwip
(如果您想确认每个删除操作)。 遗憾的是,你不能直接在提示中输入一个空值,因为无法区分这个输入和通过 Escape 键取消(除非你将g:subversivePromptWithActualCommand
设置为1
,那样就可以正常工作)
设置
g:subversivePromptWithCurrent
- 当设置为1
时,提示将包含正在被替换的文本。如果你想对其进行编辑,这可能会很有用。默认值:0
g:subversiveCurrentTextRegister
- 设置后,指定的寄存器将被填充为正在被替换的文本。这可以作为g:subversivePromptWithCurrent
的替代方案,这样你可以在提示中按<c-r>r
(假设你设置为'r'
)来编辑它,否则直接输入就可以进行完全替换。g:subversivePromptWithActualCommand
- 当设置为1
时,它将提示原生 vim 替换命令,而不是仅提示替换文本。资深 vim 用户可能更喜欢这种方式,因为他们可以自行调整各种替换标志。默认值:0
g:subversivePreserveCursorPosition
- 当设置为1
时,应用替换时光标不会移动。默认值为0
,以匹配正常的 vim 行为。
与 abolish.vim 的集成
如果你也安装了 vim-abolish,那么你可以考虑添加类似以下的映射:
nmap <leader><leader>s <plug>(SubversiveSubvertRange)
xmap <leader><leader>s <plug>(SubversiveSubvertRange)
nmap <leader><leader>ss <plug>(SubversiveSubvertWordRange)
这将表现得与 <leader>s
相同,只是它将执行 abolish 的 'subvert' 而不是使用 vim 内置的替换命令。这将应用替换并保留原始单词的大小写。例如:
在这个例子中,我们将光标移到 foo
上,然后执行 <leader><leader>seie
,然后输入 bar
,这将替换所有 foo
的实例,不管大小写如何。
这可以是一种非常方便的快速重命名方式。
正如你所预期的,<leader><leader>ss
映射的工作方式类似,只是它只匹配包含单词边界的完整单词。
同样,还有一些替代性的插件,如果你喜欢的话,它们将使用默认寄存器而不是提示:
nmap <leader><leader>s <plug>(SubversiveSubvertRangeNoPrompt)
xmap <leader><leader>s <plug>(SubversiveSubvertRangeNoPrompt)
nmap <leader><leader>ss <plug>(SubversiveSubvertWordRangeNoPrompt)
与 yoink 的集成
请注意,如果你在 vim-subversive 旁边安装了 vim-yoink,那么粘贴后的 yoink 交换功能也将自动与 subversive(单一动作)替换一起工作。换句话说,假设使用默认映射,你可以执行 siw
,然后按 <c-n>
/ <c-p>
在 yoink 历史中的不同复制内容之间切换。
Subversive 还提供了一个插件来替换可视模式下的粘贴,以便在那里也提供粘贴后的交换:
xmap s <plug>(SubversiveSubstitute)
xmap p <plug>(SubversiveSubstitute)
xmap P <plug>(SubversiveSubstitute)
现在,如果你在可视模式下按 p
,你可以像在普通模式下粘贴时一样在不同的复制内容之间切换。