Macro Vim en cada línea de selección visual

85

Me gustaría ejecutar una macro en cada línea de una selección, en lugar de sumar el número de líneas en mi cabeza. Por ejemplo, podría escribir una macro para transformar:

Last, First

Dentro

First Last

y me gustaría que se ejecutara en todas estas líneas:

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

¿Alguna idea de los gurús de Vim?

EDITAR: Esto es solo un ejemplo, obviamente esto es triviamente regexable, pero hay otras instancias que surgen que no son tan fáciles que preferiría usar macros.

Stefan Mai
fuente
1
Para ser honesto, probablemente haría esta tarea en particular con expresiones regulares. Pero la pregunta sigue siendo válida para casos más complejos.
Jamie Wong
¿Por qué vim? En mi opinión, sed es más apropiado.
kokosing
8
@kogut: ¿Por qué salir de su editor para editar su texto con una expresión regular de una línea?
Stephen
1
Ok, has
entendido

Respuestas:

152

Suponga que tiene una macro qque se ejecuta (y permanece) en una sola línea. Entonces podría ejecutarlo en cada línea de su selección con:

:'<,'>normal @q

(si ya tiene un grupo de líneas seleccionadas, presionar :produce :'<,'>en la línea de comando)

Por ejemplo, la siguiente macro pone en mayúscula cada palabra menos la primera de una línea:

:let @q="^dwgU$P"

Entonces ejecutándolo en lo siguiente (donde +se seleccionan las líneas)

 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 el normal @qcomando anterior , 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.
rampion
fuente
6
:let @q="^wgU$"
1
@rampion: ¿hay un error tipográfico en tu comando? para mí solo funciona así::'<,'>normal! @q
oliver
3
@oliver: compruebe sus asignaciones; es posible que haya reasignado @q. De :help normal- "Si se proporciona [!], Las asignaciones no se utilizarán".
rampion
2
@rampion: maldita sea ... ¡tienes razón! Utilizo yankring y aparentemente hay un problema con esto: ... No se puede ejecutar una macro con ": normal @a". Todavía no es posible, pero puede ejecutarlo con ": normal! @A" (de los documentos de ayuda de yankring)
oliver
1
Personalmente, me gusta el mapa @en modo visual como esto: vnoremap @ :normal @. De esa manera, aún puede hacer @alo que espera (aunque luego debe presionar Enter :()
LondonRob
19

Seleccione las líneas y luego presione :para ingresar al modo de comando. Vim se completará automáticamente '<,'>, lo que restringe el rango a las líneas seleccionadas. Para su ejemplo, puede usar el :scomando para hacer el intercambio:

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

Esto intercambiará dos palabras separadas por una coma en cada línea de la selección visual.

También puede usar '<y '>como cualquier otro marcador o posición de línea, por ejemplo, como parte de un comando de movimiento, por lo que en el modo normal d'<se eliminará desde la posición actual del cursor hasta el inicio de la primera línea en la selección visual. Las marcas permanecen vigentes incluso si el bloque ya no se resalta visualmente.

Si desea reproducir una macro grabada en cada línea, debe ejecutar la macro con el :normalcomando. Desafortunadamente, el :normalcomando no opera en un rango de líneas, pero puede solucionarlo con el :globalcomando. Esto ejecuta un :excomando en cada línea que coincide con una expresión regular, por lo que puede hacer esto:

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

Explicación:

:'<,'>       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
fuente
Esta es mejor que la respuesta aceptada porque admite macros que agregan nuevas líneas.
Jan Warchoł
@Dave, Kirby Quizás sería mejor intercambiar ^con ellos .para hacer que la macro se ejecute solo en líneas que tengan algo de texto, ¿no?
Sergio Araujo
1

Puede agregar la función a continuación a su ~/.vimrco simplemente copiarla en su navegador y ejecutar:@+

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

La ventaja es que puede aplicar cualquier macro en la selección visual. Debe dar la letra macro como argumento, como:

:Rover a
Sergio Araujo
fuente