最佳的解决方案是:
cw(<C-R><C-P>")<Esc>w.w.ZZ
接着我尝试去做...
cw(<C-R>")<Esc>w.w.ZZ
但是随后的文本变成了:
(one) (one)
(one)
代替
(one) (two)
(three)
有人能帮我理解为什么在这两个命令中,"." 的行为不同吗?
<BS>
在这里涉及)。关于如何通过“.”重复操作,我不知道(您需要查看源代码或询问vim_dev邮件列表)。基本上,它使不替换字符!
<C-R><C-O>
命令本身进入“.”寄存器,而不是在给出命令时寄存器中的文字。这意味着当您使用“.”重复操作时,您将获得指定寄存器中的任何内容,而不仅仅是再次插入相同的文字。(
,后跟 one
,后跟 )
。(
,插入默认寄存器的寄存器内容,插入 )
。:reg .
列出 ".
寄存器内容来查看效果。由于被接受的答案解释了CTRL-R CTRL-R
和CTRL-R CTRL-O
之间的区别,但没有回答为什么.
表现出它的特点,而且文档也不是很有帮助,我在源代码中进行了一些挖掘。
当编辑器遇到控制字符时,比如 CTRL-H
,它会执行该命令(在这种情况下是退格),而不是插入该字符。所以在插入模式下,
Hello<CTRL-H>World
HellWorld
CTRL-V
,那么字面上的控制字符将作为文本插入。因此,Hello<CTRL-V><CTRL-H>World
Hello^HWorld
其中 ^H
实际上只是使用 CTRL-H
键得到的字符的表示。
如果你想要插入一个寄存器中的文本,该怎么办呢?只用 CTRL-R
行不行?实际上,CTRL-R
插入文本就好像你在键盘上输入一样。因此,我们可以使用 CTRL-V
来欺骗 Vim 模拟 CTRL-R CTRL-R
!假设我们要插入的文本在第一行:
1| Hello^HWorld
如果我们仅仅将其放在插入模式下,那么我们将会遇到麻烦:
"ay$o
<CTRL-R>a --> 2| HellWorld
:s/<CTRL-V><CTRL-H>/<CTRL-V><CTRL-V>&
"ay$o
<CTRL-R>a --> 2| Hello^HWorld
这样我们就可以得到 Hello^HWorld
,就像我们想要的一样。
现在你基本上知道了 CTRL-R CTRL-R
是如何工作的——它在每个字符之前插入 ^V
,确保每个字符都是按字面意义插入而不是仿佛已经键入。
插入模式使用 vgetorpeek
读取字符。这有三个部分,我们可以简化为两个:
当你使用 CTRL-R
或 CTRL-R CTRL-R
时,它将调用 insert_reg
。该函数将注册内容插入到 stuffbuffer 中,因此 Vim 将以 仿佛正在输入 的方式读取它。
在 CTRL-R CTRL-R
的情况下,我们会在每个特殊字符(除了 Tab**)之前插入 CTRL-V
到 stuffbuffer 中。因此,这与仅使用正则表达式和 CTRL-R
没有什么不同——只是更加方便。
故事的道德是,当你使用 CTRL-R [CTRL-R]
时,.
命令只会看到你键入的一串文本。
但对于 CTRL-R CTRL-O
和 CTRL-R CTRL-P
,情况完全不同。这些功能显然是在 Bram 修复鼠标粘贴无法通过 .
正确重复的错误时添加的。我们不使用 insert_reg
,而是调用 do_put
,它直接将注册内容放入文本中,不需要经过任何解释按键序列的步骤。
CTRL-R CTRL-R
,Tabs也不会被插入字面上,但使用CTRL-R CTRL-O
会被插入字面上。在家里试试可见空格。我认为这就是:help中神秘的“不替换字符!”一行的含义。AppendCharToRedobuff
,以便.
将使用CTRL-R CTRL-O
重复!/* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */
AppendCharToRedobuff(Ctrl('R'));
AppendCharToRedobuff(fix_indent ? Ctrl('P') : Ctrl('O'));
AppendCharToRedobuff(regname == 0 ? '"' : regname);
CTRL-R CTRL-O
来提取寄存器,并且每次重复时抓取寄存器的内容。。
这就是为什么你会看到不同的行为:
1| one two
2| three
cw(<C-R><C-P>")<Esc>w.w.
1| (one) (two)
2| (three)
cw
会将 "two" 和 "three" 分别更新到 "
寄存器中,然后 <C-R><C-P>
命令会重新读取 "
寄存器。如果我们只使用 <C-R>"
(或者 <C-R><C-R>"
,在这里没有区别),重复执行的操作只会再次插入 "one"。cw(<C-R>")<Esc>w.w.ZZ
1| (one) (one)
2| (one)
:reg .
在每个版本后查看.
寄存器中的差异,尽管我不知道.
寄存器如何对应.
操作。
<CTRL-V><Tab>
,即使您设置了:set expandtab
,您也会得到一个制表符,因为<CTRL-V>
强制使用字面上的Tab
字符。Something<CTRL-V><Tab>Something
复制到寄存器中,然后尝试使用<CTRL-R><CTRL-R>
进行插入,则选项卡会扩展为空格,就像只使用<CTRL-R>
一样。这是由stuffescaped
函数解释的,出于某种原因,在制表符之前不插入<CTRL-V>
。<CTRL-R><CTRL-O>
不需要<CTRL-V>
(实际上会将其作为文字^V
字符插入!),因此制表符保持不变 - 或者像Bram所说的那样,
不替换字符!
:h i_ctrl-r_ctrl-p
? - romainl