如何在<CR>不添加 ?<LF>



我最近一直在玩vim宏(目前在MacVim中),有时我喜欢使用例如:let @a='(macro keystrokes)'将宏显式分配到寄存器中。这通常工作得很好,但我发现了一个奇怪的行为,每当我分配一个以Carriage Return/^M结尾的字符串值时,vim会在将其放入寄存器之前自动在末尾添加一个Linefeed/^J,这会影响宏的执行!

示例:假设我录制了一个简单的宏,该宏进入插入模式,键入"嘿",退出插入模式,然后按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会导致它多走一行,所以它实际上正在改变行为。

有人知道为什么要添加这个额外的字符吗?有人知道我如何在不添加额外^J的情况下将以^M结尾的字符串值放入寄存器(或任何变量)吗?

一些快速检查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:

但是,请注意,对于以<CR>或<NL>字符(回车或换行)。这是因为,如:help:let-@中所述,在这些条件下,Vim将把寄存器视为"lineise"。这样做的原因是为了使寄存器设置为:在处理拖动/删除的文本时,让"正确的方式"操作,但在处理录制的宏时,这可能会引起头痛。可能的解决方法包括使用setreg()函数或在宏的末尾添加"no-op"命令,例如<ESC>。有关详细信息,请参阅vim_dev上关于:let命令的意外行为的讨论。

因此,您有几个选项:使用setreg()或在使用let时向字符串添加某种非操作序列(<ESC>)。

为了使用let轻松插入特殊密钥,只需使用双引号:

:let @a="ihey<Esc><Return><Return>"

如果使用单引号,vim将插入:<Esc><Return><Return>而不是它们的函数

最新更新