Puis-je répéter une macro avec «l'opérateur point»?

15

Puis-je répéter une macro avec la .commande? Par exemple, j'aimerais pouvoir taper:

@q...

et le faire appeler efficacement @q4 fois. Avec le comportement par défaut, cela ne fonctionne que si « q » est titulaire d' une seule commande, par exemple dw, xou iHello<esc>. (Cela a du sens cependant, car '.' Répète le dernier changement , pas les dernières frappes / commandes)

J'aimerais aussi avoir ce travail avec des comptes. Par exemple, en tapant:

3@q.

serait effectivement la même chose que de courir @q6 fois. Comment puis-je configurer ce comportement?

James
la source
1
Pas exactement ce que vous demandez, mais ce sera peut-être utile github.com/wincent/replay . Ceci enregistre enfin la macro enregistrée et la rejoue en appuyant surEnter
grodzik
Pour info, @@répète la dernière macro, donc si vous demandez ceci pour des mappages et autres, cela devrait fonctionner pour vous.
Shahbaz

Réponses:

7

Essayez ceci. Il remappe @pour que g@(plus un mouvement factice l) soit utilisé par la suite, devenant ainsi le dernier opérateur et sujet à la répétition avec ..

" 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()

J'ai essayé de gérer autant de cas d'angle que je peux penser. Vous pouvez répéter @:avec .. Compte @ou .est conservé pour les presses suivantes de ..

C'est délicat et je ne suis pas convaincu que quelque chose ne se cassera pas quelque part en cours de route. Donc, aucune garantie, garantie ou promesse avec celui-ci.

Personnellement, je vais bien avoir une différence entre les répétitions à grain fin de .pour le dernier changement et les répétitions macro de @@.

ÉDITER

J'ai pensé, étant allé aussi loin, que je pourrais aussi bien ajouter du code supplémentaire qui permettra d'appuyer .immédiatement après l'enregistrement d'une macro pour la lire.

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()
Antony
la source
Cela fonctionne très bien! Depuis la publication de cette question, mon flux de travail a changé, donc je ne veux plus vraiment pouvoir répéter les macros avec des points. Cependant, cela fonctionne très bien, donc je l'accepterai de toute façon (bien que je ne l'ajouterai probablement pas à mon .vimrc)
James
Pas de soucis, problème intéressant malgré tout!
Antony
1
Modifier: permet de lire une macro .immédiatement après l'enregistrement.
Antony
Je pense que \<plug>qstopdevrait être avant qdans la fonction QStart
Steve Vermeulen
6

Pour répéter votre dernière macro, vous pouvez @@donc 3@@exécuter essentiellement @q 3 fois. Cependant, les frappes @ peuvent être lourdes, donc dans mon .vimrc j'ai les lignes:

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

Cela me permet d'utiliser ma clé de repère (,) plus m pour exécuter la dernière macro. Ensuite, vous pouvez faire précéder cela d'un nombre pour répéter la macro.

3,mEst maintenant équivalent à 3@@. Mêmes touches totales et pas besoin de maintenir la touche Maj enfoncée.

EDIT : En repensant cela, j'ai trouvé une nouvelle macro. nmap <leader>. @@ Cela fonctionne également lorsqu'il est précédé d'un nombre, il en 3,.est de même maintenant 3@@.

Shadoath
la source
L'OP veut 3@q.fonctionner @q6 fois. Cela ne fait pas ça.
user41805
En relisant votre question, je ne suis pas sûr que cela y réponde. Pouvez-vous donner un exemple de la date d'utilisation 3@q.? Il semblerait que vous pourriez aussi bien l'ajouter avec un décompte. J'ai tendance à définir une recherche avant de commencer une macro, puis à l'utiliser ndans la macro pour sauter au début de l'endroit où elle peut être rejouée.
Shadoath
5

Vous pouvez enregistrer l'utilisation d'une macro dans une autre macro et répéter cela.

qqdwq
qr2@qq

Maintenant, 3@rc'est comme courir @qsix fois.

jjaderberg
la source
1

Par défaut spacedans vim est "déplacer vers la droite 1 caractère" qui est déjà couvert par l, j'ai donc remappé l'espace pour réexécuter une macro à partir du tampon q:

noremap <Space> @q

Pour l'utiliser, enregistrez simplement une macro avec d' qqabord, arrêtez l'enregistrement avec qpuis appuyez sur spacepour relire.

brain_bacon
la source
Pour votre information, pour la raison que vous déclarez (ce n'est pas une clé obligatoire), beaucoup de gens utilisent l'espace comme leur clé de leader, donc il pourrait ne pas y avoir autant de personnes libres que vous le pensez. :)
B Layer
0

Comme je n'utilise pas ,et que j'aime une solution simple et facile à taper, cela fonctionne pour moi:

:map , @@
Neil McGill
la source