简体   繁体   English

Vim:通过映射记录宏进入插入模式

[英]Vim: record macro entering insert mode via mapping

I'm trying to have remap i/c/o/a and friends to always record a macro. 我正在尝试重新映射i / c / o / a和朋友以便始终记录宏。 But the keypress that actually brings me into insert mode is not recorded (explained below). 但实际上将我带入插入模式的按键不会被记录下来(如下所述)。

For example, if we have: 例如,如果我们有:

nnoremap i qzi
inoremap <esc> <esc>q

Ideally, this means that when I enter insert mode ( i ), I also start recording to register z . 理想情况下,这意味着当我进入插入模式( i )时,我也开始录制以注册z And when I leave ( <esc> ), we stop recording. 当我离开( <esc> )时,我们停止录音。 So register z should have the entire sequence needed to repeat what I did in insert mode. 因此,寄存器z应该具有重复我在插入模式中所做的所需的整个序列。

But then if I try to type in insert mode (eg, ihelloworld<esc> ) and then check :registers a , I get 但是如果我尝试输入插入模式(例如, ihelloworld<esc> )然后检查:registers a ,我得到

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

Notice how the i command is not included -- only what i typed in insert mode is. 注意i命令是如何被包含的 - 只有我在插入模式下键入的是。

Why is this happening? 为什么会这样? What can I do to get around it? 我该怎么做才能绕过它?

I also noticed that if I just typed qzihelloworld<esc> normally, the z register DOES contain ihelloworld<esc> (with the i ). 我还注意到,如果我只是正常输入qzihelloworld<esc> ,那么z寄存器包含ihelloworld<esc> (带有i )。

For those interested, I'm doing trying to do this because certain operations break 'repeat last command (the period key . )'. 对于那些感兴趣的人,我正在尝试这样做,因为某些操作会破坏'重复最后一个命令(句号键) . ' For example, if you use <co> or move around while insert-mode, . 例如,如果您使用<co>或在插入模式下移动, . will only repeat the last segment of your insert mode. 只会重复插入模式的最后一段。 In particular, I'm trying to find a workaround for an autoclosing plugin 特别是,我正在尝试找到一个autoclosing插件的解决方法

As @Carpetsmoker explains why it doesn't get recorded: 正如@Carpetsmoker解释为什么它没有被记录:

From :help q 来自:help q

The 'q' command is disabled while executing a register, and it doesn't work inside a mapping and :normal. 执行寄存器时禁用'q'命令,它在映射中不起作用,并且:normal。

So that explains why it doesn't work ... 这就解释了为什么它不起作用......


A solution: 一个解法:

As the command (eg, i ) in the mapping is not recorded, a solution is to prepend it to the recorded buffer when leaving insert mode. 由于未记录映射中的命令(例如, i ),因此解决方案是在离开插入模式时将其预先添加到记录的缓冲区。

To distinguish between i , a , o , etc, you can store the command in a variable, and then prepend that to the recorded macro: 要区分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>    

Simply prepending i (etc.) to the macro doesn't work (for me) since it triggers the mapping for i . 简单地将i (等)添加到宏中(对我来说)不起作用,因为它触发i的映射。 Calling it with normal! normal!打电话吧normal! fixes that. 解决了这个问题。

Another option is to modify the macro to enter insert using startinsert (combined with suitable movements to emulate i , a , o , etc.) by prepending the macro like this 另一种选择是修改宏以使用startinsert输入insert(结合适当的动作来模拟iao等),方法是预先设置这样的宏

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

caveat: Your rationale for wanting this: 警告:你想要这个的理由:

For example, if you use <co> or move around while insert-mode, . 例如,如果您使用<co>或在插入模式下移动. will only repeat the last segment of your insert mode. 只会重复插入模式的最后一段。

( my emphasis ) needs the warning that "moving around" (with arrow keys) does not work (at least in my quick tests) without additional hacking, as the arrow keys send an <esc> ... sequence, triggering the end of the recording mapping for <esc> . 我的重点 )需要警告“移动” (使用箭头键)不起作用(至少在我的快速测试中)没有额外的黑客攻击,因为箭头键发送<esc> ...序列,触发结束<esc>的录制映射。 co will work though, so you can move around (slowly) with eg <co> h (for moving left). co会工作,所以你可以移动(慢慢),例如<co> h (向左移动)。

Another problem is that replaying it as a macro does not work (with this solution at least, perhaps due to the use of normal! ) if you have newlines, etc., in the recorded macro. 另一个问题是,如果在录制的宏中有新行等,将它重放为宏不起作用(至少使用此解决方案,可能是由于使用了normal! )。 A solution to that is to execute the buffer instead of replaying it as a macro. 解决方案是execute缓冲区而不是将其作为宏重放。 That is, :exe @z instead of @z for instance with the mapping 也就是说:exe @z例如,使用映射来代替:exe @z而不是@z

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM