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

时间:2013-11-24 05:18:00

标签: macros special-characters vim 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

到目前为止一直很好,并且通过键入@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

2 个答案:

答案 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>而不是其功能