Vim:通过映射

时间:2015-05-05 21:53:16

标签: vim macros

我试图重新映射i / c / o / a和朋友以便始终录制宏。但实际上将我带入插入模式的按键不会被记录下来(如下所述)。

例如,如果我们有:

nnoremap i qzi
inoremap <esc> <esc>q

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

但是如果我尝试输入插入模式(例如ihelloworld<esc>)然后检查:registers a,我就会

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

注意如何不包含i命令 - 只有我在插入模式下键入的内容。

为什么会这样?我该怎么做才能解决它?

我还注意到,如果我只是正常输入qzihelloworld<esc>z寄存器包含ihelloworld<esc>i)。

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

1 个答案:

答案 0 :(得分:3)

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

来自:help q

  

&#39; q&#39;执行寄存器时命令被禁用,它在映射中不起作用,并且:normal。

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

解决方案:

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

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

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 

警告:您想要这样做的理由:

  

例如,如果您在插入模式下使用<c-o>移动,则.将仅重复插入模式的最后一段。

我的重点)需要警告&#34;移动&#34; (带箭头键)不起作用(至少在我的快速测试中)没有额外的黑客攻击,因为箭头键发送<esc> ...序列,触发<esc>的录制映射结束。 c-o会起作用,所以你可以移动(慢慢地)移动,例如<c-o> h(左移)。

另一个问题是将它重播为宏不起作用(至少使用此解决方案,可能是由于使用了normal!)如果您有新行等等,录制的宏。解决方法是execute缓冲区而不是将其作为宏重放。也就是说,:exe @z代替@z,例如映射

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