【问题标题】:Vim: record macro entering insert mode via mappingVim:通过映射记录宏进入插入模式
【发布时间】:2015-05-07 04:12:51
【问题描述】:

我正在尝试重新映射 i/c/o/a 和朋友以始终记录宏。但是实际上使我进入插入模式的按键没有被记录(解释如下)。

例如,如果我们有:

nnoremap i qzi
inoremap <esc> <esc>q

理想情况下,这意味着当我进入插入模式 (i) 时,我也会开始录制以注册 z。当我离开 (&lt;esc&gt;) 时,我们停止录制。所以寄存器 z 应该具有重复我在插入模式下所做的操作所需的整个序列。

但是如果我尝试输入插入模式(例如,ihelloworld&lt;esc&gt;)然后检查:registers a,我会得到

---Registers---
"z   helloworld^[

注意i 命令不包括在内——只有我在插入模式下键入的内容。

为什么会这样?我能做些什么来绕过它?

我还注意到,如果我只是正常输入qzihelloworld&lt;esc&gt;z 寄存器确实包含ihelloworld&lt;esc&gt;(带有i)。

对于那些感兴趣的人,我正在尝试这样做,因为某些操作会破坏“重复上一个命令(句点键 .)”。例如,如果您使用&lt;c-o&gt; 或在插入模式下四处移动,. 将只重复插入模式的最后一段。特别是,我正在尝试为自动关闭插件找到解决方法

【问题讨论】:

标签: vim macros


【解决方案1】:

@Carpetsmoker 解释了为什么它没有被记录:

来自:help q

'q' 命令在执行寄存器时被禁用,它在映射和 :normal 中不起作用。

这就解释了为什么它不起作用......


解决方案:

由于映射中的命令(例如,i)没有被记录,一个解决方案是在离开插入模式时将其添加到记录的缓冲区中。

要区分iao等,可以将命令存储在变量中,然后将that添加到录制的宏中:

nnoremap i :let b:mode="i"<cr>qzi
nnoremap a :let b:mode="a"<cr>qza
nnoremap o :let b:mode="o"<cr>qzo

inoremap <Esc> <Esc>q :let @z=":normal! ".b:mode.@z<CR>    

简单地将i(等)添加到宏(对我而言)不起作用,因为它会触发i 的映射。用normal! 调用它可以解决这个问题。

另一种选择是修改宏以使用startinsert 进入插入(结合适当的动作来模拟iao 等),方法是在宏前面添加这样的宏

:let @z=":startinsert^M".@z 

警告:您想要这个的理由:

例如,如果您在插入模式下使用&lt;c-o&gt;移动. 将只重复插入模式的最后一段。

我的重点)需要警告 “四处走动”(使用箭头键)在没有额外黑客攻击的情况下不起作用(至少在我的快速测试中),因为箭头键发送&lt;esc&gt; ... 序列,触发&lt;esc&gt; 的记录映射结束。 c-o 会起作用,所以你可以(慢慢地)移动,例如&lt;c-o&gt; h(用于向左移动)。

另一个问题是如果您在录制的文件中有换行符等,则将其作为宏重放是行不通的(至少使用此解决方案,可能是由于使用了normal!)宏。对此的解决方案是execute 缓冲区,而不是将其作为宏重放。也就是说,:exe @z 而不是 @z 例如使用映射

nnoremap <space>z :execute @z<cr>

【讨论】:

  • 你应该在q:let之间添加一个空格。;我的回答有这个是有原因的。输入:startinsert&lt;Esc&gt; 看看为什么 :-) 另外,还有更多方法可以进入插入模式; this page should list them all
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
相关资源
最近更新 更多