Macro Vim em todas as linhas de seleção visual

86

Eu gostaria de executar uma macro em cada linha de uma seleção, em vez de totalizar o número de linhas na minha cabeça. Por exemplo, posso escrever uma macro para transformar:

Last, First

Para dentro

First Last

e gostaria que fosse executado em todas estas linhas:

Stewart, John 
Pumpkin, Freddy
Mai, Stefan
...

Alguma ideia dos gurus do Vim?

EDITAR: Este é apenas um exemplo, obviamente, é trivialmente regexável, mas há outras instâncias que aparecem que não são tão fáceis que eu prefiro usar macros.

Stefan Mai
fonte
1
Para ser honesto, provavelmente faria essa tarefa específica com regex. Mas a pergunta ainda é válida para casos mais complexos.
Jamie Wong
Por que vim? Na minha opinião, sed é mais apropriado.
kokosing
8
@kogut: Por que sair de seu editor para editar seu texto com um regex de uma linha?
Stephen
1
Ok, você entendeu;)
kokosing

Respostas:

154

Suponha que você tenha uma macro qque foi executada (e permaneceu) em uma única linha. Então, você pode executá-lo em cada linha de sua seleção com:

:'<,'>normal @q

(se você já tiver um grupo de linhas selecionado, acertando :produz :'<,'>na linha de comando)

Por exemplo, a macro a seguir coloca todas as palavras em maiúscula, exceto a primeira em uma linha:

:let @q="^dwgU$P"

Então, executando-o no seguinte (onde as +linhas são selecionadas)

 0000: a long long time ago
 0001: in a galaxy far away
+0002: naboo was under an attack
+0003: and i thought me and qui-gon jinn
+0004: could talk the federation in
 0005: to maybe cutting them a little slack.

Com o normal @qcomando acima , produz:

 0000: a long long time ago
 0001: in a galaxy far away
 0002: naboo WAS UNDER AN ATTACK
 0003: and I THOUGHT ME AND QUI-GON JINN
 0004: could TALK THE FEDERATION IN
 0005: to maybe cutting them a little slack.
rampion
fonte
@Roger Pate: bem, sim, se você quiser jogar golfe :)
rampion
1
@rampion: há um erro de digitação em seu comando? para mim só funciona assim::'<,'>normal! @q
oliver
3
@oliver: verifique seus mapeamentos - você pode ter remapeado @q. De :help normal- "Se [!] For fornecido, os mapeamentos não serão usados."
rampion
2
@rampion: droga ... você está certo! Eu uso o yankring e aparentemente há um problema com isso: ... Você não pode executar uma macro com ": normal @a". Ainda não é possível, mas você pode executá-lo com ": normal! @A" (da documentação de ajuda do yankring)
oliver
1
Eu pessoalmente gosto de mapear @em modo visual como este: vnoremap @ :normal @. Dessa forma, você ainda pode fazer @ao que esperava (embora tenha que pressionar enter depois :()
LondonRob
19

Selecione as linhas e pressione :para entrar no modo de comando. O Vim irá preencher automaticamente '<,'>, o que restringe o intervalo às linhas selecionadas. Para seu exemplo, você pode usar o :scomando para fazer a troca:

:'<,'>s/\(\w\+\), \(\w\+\)/\2, \1/

Isso trocará duas palavras separadas por vírgula em cada linha na seleção visual.

Você também pode usar '<e '>como qualquer outro marcador ou posição de linha, por exemplo, como parte de um comando de movimento, portanto, no modo normal, d'<o apagará da posição atual do cursor até o início da primeira linha na seleção visual. As marcas permanecem em vigor mesmo que o bloco não seja mais destacado visualmente.

Se você deseja reproduzir uma macro gravada em cada linha, você precisa executar a macro com o :normalcomando. Infelizmente, o :normalcomando não opera em um intervalo de linhas, mas você pode corrigir isso com o :globalcomando. Isso executa um :excomando em cada linha que corresponde a um regex, então você pode fazer o seguinte:

:'<,'>g/^/ norm @a

Explicação:

:'<,'>       for every line in the visual block
g/^/         on every line that matches the regex /^/ - i.e. every line
norm         run in normal mode
@a           the macro recorded in a
Dave Kirby
fonte
Isso é melhor do que a resposta aceita porque oferece suporte a macros que adicionam novas linhas.
Jan Warchoł
@Dave, Kirby Talvez seja melhor trocar ^com .fazer a macro rodar apenas em linhas que contenham algum texto, não é?
SergioAraujo
1

Você pode adicionar a função abaixo ao seu ~/.vimrcou simplesmente copiá-la no seu navegador e rodar:@+

fun! RunMacroOverSelection(macroname)
    execute "'<,'>normal @". a:macroname
endfun
com -nargs=1 Rover :call RunMacroOverSelection(<f-args>)
nnoremap <leader>r :Rover<space>

A vantagem é que você pode aplicar qualquer macro na seleção visual. Você precisa dar a letra da macro como argumento, como:

:Rover a
SergioAraujo
fonte