我最近一直在使用vim宏(目前在MacVim中),有时我喜欢使用例如明确地将宏分配到寄存器中。 :let @a='(macro keystrokes)'
。这通常工作正常,但我发现了一种奇怪的行为,其中任何时候我分配一个以Carriage Return / ^ M结尾的字符串值,vim会在将它放入寄存器之前自动将Endfeed / ^ J添加到结尾,这会影响执行宏!
示例:假设我录制了一个进入插入模式的简单宏,键入“hey”,退出插入模式,然后按两次Enter键向下走2行。我通过输入qaihey<Escape><Enter><Enter>q
将其记录到寄存器@a中,它将以下内容存储在@a:
ihey^[^M^M
到目前为止一直很好,并且通过键入@a
来执行宏就可以实现它的目的。我可以将这个相同的宏放入寄存器@a的另一个完全正确的方法是将整个事物(ihey<Ctrl-V><Escape><Ctrl-V><Enter><Ctrl-V><Enter>
)输入缓冲区,然后用"ay
进行操作 - 最终结果是相同的。但这是奇怪的事情 - 假设我只想使用let
语句将该字符串直接分配给@a:
:let @a='ihey^[^M^M'
现在,如果我输入:reg
来查看它所显示的值,那么由于某种原因,最后会有一个额外的^J
:
"8 ...
"9 ...
"a ihey^[^M^M^J
"b ...
使用额外的^J
会导致它在执行宏时向下一行,所以它实际上改变了行为。
有人知道为什么要添加这个额外的角色?任何人都知道如何将一个以^M
结尾的字符串值放入寄存器(或任何变量),而不需要额外添加^J
?
答案 0 :(得分:6)
快速查看vim帮助文件说:
:let @{reg-name} = {expr1} *:let-register* *:let-@* ... If the result of {expr1} ends in a <CR> or <NL>, the register will be linewise, otherwise it will be set to characterwise.
换句话说,使用回车结束字符串将使Vim将其解释为结束行
快速搜索来自VimTips wiki的this:
但请注意,上述方法使用:let将无法按预期的方式对以#&lt;结尾的任何宏起作用。 CR&gt;或者&lt; NL&gt;字符(回车或换行)。这是因为,如:help:let- @中所述,Vim会在这些条件下将寄存器视为“linewise”。这样做的原因是使寄存器设置为:在处理被拔出/删除的文本时让“行为正确”,但在处理录制的宏时会引起麻烦。可能的解决方法包括使用setreg()函数或在宏的末尾添加“no-op”命令,例如&lt; ESC&gt;。有关详细信息,请参阅有关:let命令的意外行为的vim_dev讨论。
所以你有几个选择:当你使用setreg()
时,使用let
或者在字符串中添加某种无操作序列(&lt; ESC&gt;)。
答案 1 :(得分:0)
要使用let轻松插入特殊键,只需使用双引号即可:
:let @a="ihey\<Esc>\<Return>\<Return>"
如果使用单引号,vim将插入:
\<Esc>\<Return>\<Return>
而不是其功能