如何在不添加<LF>的情况下将以<CR>结尾的字符串分配给vimscript变量?

mur*_*own 3 vim macros special-characters macvim

我最近一直在玩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
Run Code Online (Sandbox Code Playgroud)

到目前为止@a一切都那么好,并且通过键入来执行宏只是它应该是什么.我可以将这个相同的宏放入寄存器@a的另一个非常好的方法是将整个事物(ihey<Ctrl-V><Escape><Ctrl-V><Enter><Ctrl-V><Enter>)输入缓冲区,然后用它进行操作"ay- 最终结果是相同的.但这是奇怪的事情 - 假设我只想使用let语句将该字符串直接分配到@a :

:let @a='ihey^[^M^M'
Run Code Online (Sandbox Code Playgroud)

现在,如果我输入:reg要查看它所显示的值,那么^J由于某种原因,最后会有额外的值:

"8     ...
"9     ...
"a     ihey^[^M^M^J
"b     ...
Run Code Online (Sandbox Code Playgroud)

有额外的^J原因导致它在执行宏时会减少额外的行,所以它实际上改变了行为.

有谁知道为什么要添加这个额外的角色?任何人都知道我怎么能得到一个^M以寄存器(或任何变量)结尾的字符串值,而不需要额外^J添加?

小智 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.
Run Code Online (Sandbox Code Playgroud)

换句话说,使用回车符结束字符串将使Vim将其解释为行结尾


快速谷歌搜索给这个从VimTips维基:

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

所以你有几个选择:setreg()当你使用时,在字符串中使用或添加某种无操作序列(<ESC>)let.