Posso ripetere una macro con l '"operatore punto"?


15

Posso ripetere una macro con il .comando? Ad esempio, vorrei essere in grado di digitare:

@q...

e farlo chiamare efficacemente @q4 volte. Con il comportamento predefinito, questo funziona solo se 'q' contenente un solo comando, per esempio dw, xo iHello<esc>. (Questo ha senso però, poiché '.' Ripete l'ultima modifica , non le ultime battute / comandi)

Mi piacerebbe anche avere questo lavoro con i conteggi. Ad esempio, digitando:

3@q.

sarebbe effettivamente lo stesso di correre @q6 volte. Come posso configurare questo comportamento?


1
Non è esattamente quello che stai chiedendo, ma forse sarà utile github.com/wincent/replay . Questo registra infine la macro registrata e la riproduce premendoEnter
grodzik il

Cordiali saluti, @@ripete l'ultima macro, quindi se lo stai chiedendo per motivi di mappature e simili, dovrebbe funzionare per te.
Shahbaz,

Risposte:


7

Prova questo. Rimappa in @modo che g@(più un movimento fittizio l) venga utilizzato in seguito, diventando così l'ultimo operatore e soggetto a ripetizione ..

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

Ho provato a gestire tutti i casi angolari che mi viene in mente. Puoi ripetere @:con .. Conta @o .viene conservato per le successive pressioni di ..

Questo è difficile, e non sono convinto che qualcosa non si romperà da qualche parte lungo la strada. Quindi nessuna garanzia, garanzia o promessa con questo.

Personalmente, sto bene avendo una differenza tra le ripetizioni a grana fine .dell'ultima modifica e le ripetizioni macro di @@.

MODIFICARE

Ho immaginato, essendo andato così lontano, che potrei anche aggiungere qualche codice aggiuntivo che permetterà di premere .immediatamente dopo aver registrato una macro per riprodurlo.

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

Funziona alla grande! Da quando ho pubblicato questa domanda, il mio flusso di lavoro è cambiato, quindi non voglio più essere in grado di ripetere le macro con il punto. Tuttavia, funziona davvero bene, quindi lo accetterò comunque (anche se probabilmente non lo aggiungerò al mio .vimrc)
James

Nessun problema, problema interessante a prescindere!
Antony,

1
Modifica: consente di riprodurre una macro .immediatamente dopo la registrazione.
Antony,

Penso che \<plug>qstopdovrebbe essere prima qnella funzione QStart
Steve Vermeulen il

6

Per ripetere l'ultima macro è possibile utilizzare, @@quindi 3@@si eseguirà essenzialmente @q 3 volte. Tuttavia, i tasti @ possono essere ingombranti, quindi nel mio .vimrc ho le righe:

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

Questo mi permette di usare la mia chiave guida (,) più m per eseguire l'ultima macro. Quindi puoi precedere questo con un numero per ripetere la macro.

Ora 3,mè equivalente a 3@@. Stessi tasti totali e nessuna necessità di tenere premuto il turno.

EDIT : Dopo aver ripensato questo mi è venuta in mente una nuova macro. nmap <leader>. @@ Questo funziona anche quando preceduto da un numero, quindi 3,.ora mi 3@@piacerebbe vedere questo lavoro in modo che potessi passare una lettera macro e ripetere quella macro invece dell'ultima macro.


L'OP vuole 3@q.essere eseguito @q6 volte. Questo non lo fa.
user41805

Rileggendo la tua domanda non sono sicuro che questo risponda. Puoi fare un esempio di quando useresti 3@q.? Sembrerebbe che tu possa anche semplicemente anticiparlo con un conteggio. Tendo a impostare una ricerca prima di iniziare una macro, quindi utilizzare nnella macro per saltare all'inizio di dove può essere riprodotta.
Shadoath,

5

È possibile registrare l'uso di una macro in un'altra macro e ripeterlo.

qqdwq
qr2@qq

Adesso 3@rè come correre @qsei volte.


1

Per impostazione predefinita spacein vim è "sposta 1 carattere a destra" che è già coperto da l, quindi ho rimappato lo spazio per rieseguire una macro dal buffer q:

noremap <Space> @q

Per usare, basta registrare prima una macro qq, interrompere la registrazione con qe quindi premere spaceper riprodurre.


Cordiali saluti, per il motivo in cui affermi (non è una chiave richiesta) molte persone usano lo spazio come chiave principale, quindi potrebbero non esserci tante persone libere come pensi. :)
B Layer

0

Poiché non utilizzo ,e mi piace una soluzione semplice e facile da digitare, questo funziona per me:

:map , @@
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.