我可以使用“点运算符”重复一个宏吗?


15

我可以在.命令中重复一个宏吗?例如,我希望能够输入:

@q...

并有效呼叫@q4次。使用默认的行为,这只有当“Q”拥有一个命令,例如dwxiHello<esc>。(尽管这很有意义,因为'。'会重复最后一次更改,而不是最后一次击键/命令)

我也很希望这项工作能算是重要的。例如,键入:

3@q.

实际上将与运行@q6次相同。如何配置此行为?


1
并非完全符合您的要求,但也许对github.com/wincent/replay会有所帮助。此记录最后记录的宏,并在按下时重播Enter
grodzik

仅供参考,@@重复最后一个宏,因此,如果您出于映射之类的要求而这样做,那么它应该对您有用。
Shahbaz

Answers:


7

试试看。它将重新映射,@以便随后使用g@(加上伪动作l),从而成为最后一个运算符,并用重复.

" When . repeats g@, repeat the last macro.
fun! AtRepeat(_)
    " If no count is supplied use the one saved in s:atcount.
    " Otherwise save the new count in s:atcount, so it will be
    " applied to repeats.
    let s:atcount = v:count ? v:count : s:atcount
    " feedkeys() rather than :normal allows finishing in Insert
    " mode, should the macro do that. @@ is remapped, so 'opfunc'
    " will be correct, even if the macro changes it.
    call feedkeys(s:atcount.'@@')
endfun

fun! AtSetRepeat(_)
    set opfunc=AtRepeat
endfun

" Called by g@ being invoked directly for the first time. Sets
" 'opfunc' ready for repeats with . by calling AtSetRepeat().
fun! AtInit()
    " Make sure setting 'opfunc' happens here, after initial playback
    " of the macro recording, in case 'opfunc' is set there.
    set opfunc=AtSetRepeat
    return 'g@l'
endfun

" Enable calling a function within the mapping for @
nno <expr> <plug>@init AtInit()
" A macro could, albeit unusually, end in Insert mode.
ino <expr> <plug>@init "\<c-o>".AtInit()

fun! AtReg()
    let s:atcount = v:count1
    let c = nr2char(getchar())
    return '@'.c."\<plug>@init"
endfun

nmap <expr> @ AtReg()

我已经设法处理了尽可能多的极端情况。您可以重复@:使用.。计数@.保留以供以后按.

这很棘手,而且我不相信某些东西不会在途中破裂。因此,对此没有任何保证,担保或承诺。

就我个人而言,我可以.在最后一次更改的细粒度重复与的宏重复之间有所区别@@

编辑

我认为,到目前为止,我还可以添加一些其他代码,以便.在录制宏后立即按下以播放它。

fun! QRepeat(_)
    call feedkeys('@'.s:qreg)
endfun

fun! QSetRepeat(_)
    set opfunc=QRepeat
endfun

fun! QStop()
    set opfunc=QSetRepeat
    return 'g@l'
endfun

nno <expr> <plug>qstop QStop()
ino <expr> <plug>qstop "\<c-o>".QStop()

let s:qrec = 0
fun! QStart()
    if s:qrec == 1
        let s:qrec = 0
        return "q\<plug>qstop"
    endif
    let s:qreg = nr2char(getchar())
    if s:qreg =~# '[0-9a-zA-Z"]'
        let s:qrec = 1
    endif
    return 'q'.s:qreg
endfun

nmap <expr> q QStart()

这太棒了!自发布此问题以来,我的工作流程已更改,因此我真的不希望再使用点重复宏。但是,这确实很好用,所以无论如何我都会接受(尽管我可能不会将其添加到我的.vimrc
James

不用担心,有趣的问题无论如何!
安东尼

1
编辑:允许.在录制后立即播放宏。
安东尼

我认为\<plug>qstop应该q在QStart函数之前
Steve Vermeulen

6

重复上一宏,您可以用@@这样3@@会本质上运行@q 3倍。但是@击键可能很笨拙,因此在我的.vimrc文件中,我的代码行如下:

  "- Lazy macro repeat
  nmap <leader>m @@

这使我可以使用前导键(,)加m来运行最后一个宏。然后,您可以在其前面加上一个数字以重复该宏。

现在3,m等于3@@。总键数相同,无需按住shift键。

编辑:经过重新考虑,我想到了一个新的宏。 nmap <leader>. @@ 当在数字前加上数字也可以使用,因此3,.现在3@@很想看看这项工作,以便我可以传递宏字母并让该宏重复而不是最后一个宏。


OP希望3@q.运行@q6次。这不会那样做。
user41805 '17

重读您的问题,我不确定是否能回答。您能举例说明何时使用3@q.吗?似乎您不妨先加上一个数字。我倾向于在开始宏之前进行搜索,然后n在宏中使用以跳到可以重播的开始。
Shadoath

5

您可以在另一个宏中记录对宏的使用,然后重复进行。

qqdwq
qr2@qq

现在3@r就像跑了@q六遍。


1

space在vim中,默认情况下是“ move right 1 character”,已经被覆盖了l,所以我重新映射了空间以从q缓冲区重新运行宏:

noremap <Space> @q

要使用该功能,只需先录制一个宏,然后使用qq停止录制,q然后按一下space即可重播。


仅供参考,出于您声明的原因(这不是必需的密钥),很多人都将空间用作其领导者密钥,因此可能没有多少人像您想象的那样拥有空闲空间。:)
B层

0

因为我不使用,并且喜欢简单的易于键入的解决方案,所以它对我有用:

:map , @@
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.