Posso repetir uma macro com o "operador de ponto"?

15

Posso repetir uma macro com o .comando? Por exemplo, eu gostaria de poder digitar:

@q...

e faça com que ele efetivamente ligue @q4 vezes. Com o comportamento padrão, isso funciona somente se 'q' contém um único comando, por exemplo dw, xou iHello<esc>. (Isso faz sentido, pois '.' Repete a última alteração , não as últimas teclas / comandos)

Eu também adoraria ter esse trabalho com contagens. Por exemplo, digitando:

3@q.

seria efetivamente o mesmo que correr @q6 vezes. Como posso configurar esse comportamento?

James
fonte
1
Não é exatamente o que você está pedindo, mas talvez seja útil github.com/wincent/replay . Por último, registra a macro gravada e a repete pressionandoEnter
#
Para sua informação, @@repete a última macro; portanto, se você estiver perguntando isso por causa de mapeamentos e coisas do tipo, deve funcionar para você.
Shahbaz

Respostas:

7

Faça uma tentativa. Ele remapeia @para que g@(mais um movimento simulado l) seja usado posteriormente, tornando-se o último operador e sujeito a repetição ..

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

Eu tentei lidar com o maior número de casos de esquina que consigo imaginar. Você pode repetir @:com .. Conta @ou .é retido para prensas subsequentes de ..

Isso é complicado, e não estou convencido de que algo não vai quebrar em algum lugar ao longo do caminho. Portanto, não há garantias, garantias ou promessas com este.

Pessoalmente, estou bem em ter uma diferença entre as repetições refinadas de .para a última alteração e as repetições macro de @@.

EDITAR

Achei que, tendo ido tão longe, também poderia adicionar algum código adicional que permitirá pressionar .imediatamente após a gravação de uma macro para reproduzi-la.

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
fonte
Isso funciona fantástico! Desde que postei essa pergunta, meu fluxo de trabalho mudou, então não quero mais poder repetir macros com pontos. No entanto, isso funciona muito bem, então eu vou aceitá-lo de qualquer maneira (embora eu provavelmente não irá adicioná-lo ao meu .vimrc)
James
Não se preocupe, problema interessante independentemente!
Antony
1
Editar: permite reproduzir uma macro .imediatamente após a gravação.
Antony
Eu acho que \<plug>qstopdeveria estar qna função QStart antes #
Steve Vermeulen
6

Para repetir sua última macro, você pode usá- @@lo 3@@, essencialmente rodaria @ q 3 vezes. No entanto, as teclas @ podem ser difíceis de manejar, então no meu .vimrc eu tenho as linhas:

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

Isso permite que eu use minha chave de líder (,) mais m para executar a última macro. Em seguida, você pode preceder isso com um número para repetir a macro.

Agora 3,mé equivalente a 3@@. Mesmas chaves totais e não há necessidade de pressionar Shift.

EDIT : Ao repensar isso, eu vim com uma nova macro. nmap <leader>. @@ Isso também funciona quando precedido por um número. 3,.Agora, 3@@gostaria de ver esse trabalho para que eu pudesse passar uma letra de macro e repeti-la em vez da última macro.

Shadoath
fonte
O OP quer 3@q.executar @q6 vezes. Isso não faz isso.
user41805
Relendo sua pergunta, não tenho certeza de que isso responda. Você pode dar um exemplo de quando você usaria 3@q.? Parece que você também pode anexá-lo com uma contagem. Costumo definir uma pesquisa antes de iniciar uma macro e depois usá n-la para ir para o início de onde ela pode ser reproduzida.
Shadoath
5

Você pode gravar o uso de uma macro em outra macro e repetir isso.

qqdwq
qr2@qq

Agora 3@ré como correr @qseis vezes.

jjaderberg
fonte
1

Por padrão, spaceno vim é "mover para a direita 1 caractere", que já está coberto l, portanto, remapeei o espaço para executar novamente uma macro do buffer q:

noremap <Space> @q

Para usar, basta gravar uma macro qqprimeiro, interromper a gravação qe pressionar spacepara reproduzir.

brain_bacon
fonte
Para sua informação, pelo motivo em que você declara (não é uma chave obrigatória) muitas pessoas usam o espaço como chave de líder, portanto, pode haver tantas pessoas livres quanto você pensa. :)
Camada B
0

Como não uso ,e como uma solução simples e fácil de digitar, isso funciona para mim:

:map , @@
Neil McGill
fonte