¿Puedo repetir una macro con el "operador de puntos"?

15

¿Puedo repetir una macro con el .comando? Por ejemplo, me gustaría poder escribir:

@q...

y que efectivamente llame @q4 veces. Con el comportamiento por defecto, esto sólo funciona si 'Q' tiene un solo comando, por ejemplo dw, xo iHello<esc>. (Esto tiene sentido, ya que '.' Repite el último cambio , no las últimas pulsaciones / comando)

También me encantaría tener este trabajo con cuentas. Por ejemplo, escribiendo:

3@q.

sería efectivamente lo mismo que correr @q6 veces. ¿Cómo puedo configurar este comportamiento?

James
fuente
1
No es exactamente lo que está pidiendo, pero tal vez sea útil github.com/wincent/replay . Esto graba la última macro grabada y la reproduce al presionarEnter
grodzik
Para su información, @@repite la última macro, por lo que si está pidiendo esto por el bien de los mapeos y tal, debería funcionar para usted.
Shahbaz

Respuestas:

7

Prueba esto. Se reasigna @para que luego se use g@(más un movimiento ficticio l), convirtiéndose así en el último operador y sujeto a repetición con ..

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

He tratado de manejar tantos casos de esquina como puedo pensar. Puedes repetir @:con .. Cuenta @o .se retiene para imprentas posteriores de ..

Esto es complicado, y no estoy convencido de que algo no se rompa en algún lugar del camino. Entonces no hay garantías, garantías o promesas con este.

Personalmente, estoy bien teniendo una diferencia entre las repeticiones de grano fino .para el último cambio y las repeticiones macro de @@.

EDITAR

Pensé, habiendo llegado tan lejos, que también podría agregar algún código adicional que permita presionar .inmediatamente después de grabar una macro para reproducirla.

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()
Antonio
fuente
¡Esto funciona fantástico! Desde que publiqué esta pregunta, mi flujo de trabajo ha cambiado, por lo que ya no quiero poder repetir macros con punto. Sin embargo, esto funciona muy bien, así que lo aceptaré de todos modos (aunque probablemente no lo agregue a mi .vimrc)
James
No se preocupe, problema interesante independientemente!
Antony
1
Editar: permite reproducir una macro .inmediatamente después de la grabación.
Antony
Creo que \<plug>qstopdebería estar antes qen la función QStart
Steve Vermeulen
6

Para repetir la última macro se puede utilizar @@de modo 3@@que esencialmente ejecutar @q 3 veces. Sin embargo, las pulsaciones de teclas @ pueden ser difíciles de manejar, por lo que en mi .vimrc tengo las líneas:

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

Esto me permite usar mi clave de líder (,) más m para ejecutar la última macro. Entonces puede preceder esto con un número para repetir la macro.

Ahora 3,mes equivalente a 3@@. Las mismas teclas totales y no hay necesidad de mantener turno.

EDITAR : Al repensar esto, se me ocurrió una nueva macro. nmap <leader>. @@ Esto también funciona cuando está precedido por un número, por 3,.lo que ahora me 3@@encantaría ver este trabajo para poder pasar una letra macro y hacer que esa macro se repita en lugar de la última macro.

Sombra
fuente
El OP quiere 3@q.correr @q6 veces. Esto no hace eso.
usuario41805
Volviendo a leer su pregunta, no estoy seguro de que esto la responda. ¿Puedes dar un ejemplo de cuándo lo usarías 3@q.? Parece que también podrías anteponerlo con un recuento. Tiendo a establecer una búsqueda antes de comenzar una macro y luego la uso nen la macro para saltar al inicio de donde se puede reproducir.
Shadoath
5

Puede registrar el uso de una macro en otra macro y repetir eso.

qqdwq
qr2@qq

Ahora 3@res como correr @qseis veces.

jjaderberg
fuente
1

Por defecto, spaceen vim está "mover a la derecha 1 carácter" que ya está cubierto l, por lo que he reasignado el espacio para volver a ejecutar una macro desde el búfer q:

noremap <Space> @q

Para usar, solo grabe una macro con qqprimero, deje de grabar con qy luego presione spacepara reproducir.

brain_bacon
fuente
Para su información, por la razón que usted dice (no es una clave requerida), muchas personas usan el espacio como su clave de líder, por lo que es posible que no haya tantas personas libres como cree. :)
Capa B
0

Como no uso ,y me gusta una solución simple y fácil de escribir, esto funciona para mí:

:map , @@
Neil McGill
fuente