Vim Macro su ogni riga di selezione visiva


86

Vorrei eseguire una macro su ogni riga di una selezione, piuttosto che sommare il numero di righe nella mia testa. Ad esempio, potrei scrivere una macro per trasformare:

Last, First

In

First Last

e mi piacerebbe che funzionasse su tutte queste righe:

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

Qualche idea sui guru di Vim?

EDIT: Questo è solo un esempio, ovviamente è regexable banalmente, ma ci sono altri casi che vengono fuori che non sono così facili che preferirei usare le macro.


1
Ad essere onesti, probabilmente farei questo particolare compito con regex. Ma la domanda è ancora valida per casi più complessi.
Jamie Wong

Perché vim? Secondo me sed è più appropriato.
kokosing

8
@kogut: Perché uscire dall'editor per modificare il testo con un'espressione regolare di una riga?
Stephen

1
Ok, hai
capito

Risposte:


154

Supponi di avere una macro qche gira (e rimane) su una singola riga. Quindi puoi eseguirlo su ogni riga nella tua selezione con:

:'<,'>normal @q

(se hai già un gruppo di linee selezionato, premendo :produce :'<,'>sulla riga di comando)

Ad esempio, la seguente macro rende maiuscola ogni parola tranne la prima su una riga:

:let @q="^dwgU$P"

Quindi eseguendolo sul seguente (dove +sono selezionate le linee)

 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.

Con il normal @qcomando precedente , produce:

 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.

@ Roger Pate: beh, sì, se volevi giocare a golf :)
rampion

1
@ Rampion: c'è un errore di battitura nel tuo comando? per me funziona solo così::'<,'>normal! @q
oliver

3
@oliver: controlla le tue mappature - potresti aver rimappato @q. From :help normal- "Se viene fornito [!], Le mappature non verranno utilizzate."
rampion

2
@rampion: accidenti ... hai ragione! Uso lo strattone e apparentemente c'è un problema con questo: ... Non puoi eseguire una macro con ": normal @a". Non è ancora possibile, ma puoi eseguirlo con ": normal! @A" (dai documenti di aiuto di yankring)
oliver

1
Personalmente, come per mappare @in modalità visiva in questo modo: vnoremap @ :normal @. In questo modo puoi ancora fare @acome ti aspetteresti (anche se devi
premere invio

19

Selezionare le righe, quindi premere :per accedere alla modalità di comando. Vim si riempirà automaticamente '<,'>, il che limita l'intervallo alle linee selezionate. Per il tuo esempio puoi usare il :scomando per fare lo scambio:

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

Questo scambierà due parole separate da una virgola su ogni riga nella selezione visiva.

Puoi anche usare '<e '>come qualsiasi altro segnalibro o posizione di linea, ad esempio come parte di un comando di movimento, quindi in modalità normaled'< cancellerà dalla posizione corrente del cursore all'inizio della prima riga nella selezione visiva. I segni rimangono attivi anche se il blocco non è più evidenziato visivamente.

Se vuoi riprodurre una macro registrata su ogni riga, devi eseguire la macro con il :normalcomando. Sfortunatamente il :normalcomando non funziona su un intervallo di righe, ma puoi risolverlo con il :globalcomando. Questo esegue un :excomando su ogni riga che corrisponde a una regex, quindi puoi farlo:

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

Spiegazione:

:'<,'>       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

È migliore della risposta accettata perché supporta macro che aggiungono nuove righe.
Jan Warchoł

@ Dave, Kirby Forse sarebbe meglio scambiare ^con .per fare in modo che la macro venga eseguita solo su righe che hanno del testo, no?
SergioAraujo

1

Puoi aggiungere la funzione sottostante al tuo ~/.vimrco semplicemente copiarla sul tuo browser e in esecuzione:@+

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

Il vantaggio è che puoi applicare qualsiasi macro alla selezione visiva. Devi fornire la lettera macro come argomento, come:

:Rover a
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.