vim: ¿Continuar macro después del error en submacro?

14

Estoy en el proceso de embellecer algún código fuente usando vim. {1}

He creado un par de macros vim que realizan los pasos individuales: eliminar espacios en blanco al final, eliminar líneas vacías después {, eliminar líneas vacías antes {, ese tipo de cosas.

Ahora, quiero crear una macro que ejecute todas las macros individuales en secuencia. Sin embargo, una vez que finaliza la primera macro recursiva (porque ya no puede encontrar coincidencias -> error de coincidencia), mi macro "wrapper" también finaliza.

¿Hay alguna manera de hacer que una macro vim continúe después de que un submacro generó un error?

{1} Yo acerca reformatters automáticas. Incluso podría usarlos en mi problema actual. Simplemente mencioné el reformateo de la fuente por el bien del ejemplo. No publique ninguna respuesta sobre este embellecedor fuente o eso. La pregunta no se trata de reformatear el código per se , sino de las macros vim.

Ejemplo:

  • Macro 1: recorte de espacios en blanco al final qw/\s\+$d$@wq
  • Macro 2: eliminar líneas vacías antes} qe/\n\n *}dd@eq
  • Macro de envoltura - reenganche, Macro 1, Macro 2 - qr:retab@w@eq

Cuando ejecuto el reiniciador, @rse volverá a agrupar, luego ejecutará la Macro 1 hasta que no se encuentren más espacios en blanco al final, luego terminaré ( sin ejecutar la Macro 2).

Aclaración:

Lo que estoy buscando es cómo llamar a un submacro para que cuando ese submacro termine, la macro de llamada continúe.

DevSolar
fuente

Respuestas:

12

Le sugiero que use :trypara "absorber" el error del submacro.

Aquí hay un ejemplo tonto:

:let @a='f|dt|@a'
:let @q=':try|exe "norm! @a"|endtry^Mj0@q'
@q

Su macro de envoltura se vería así:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'
Peter Rincker
fuente
Si bien garyjohn proporcionó una solución alternativa para no tener un error en un submacro, esta es la única respuesta que realmente maneja dicho error. Sin embargo, tengo que disculparme; No verifiqué tu respuesta a tiempo para que obtengas la recompensa (ahora expirada) ... :-(
DevSolar
25

Si el comando que falla es una sustitución que no encuentra su patrón, por ejemplo,

:%s/foo/bar/

cuando foono existe en el búfer, puede agregar la ebandera para ignorar ese error, por ejemplo,

:%s/foo/bar/e

Ver

:help :s_flags

Puedes decirle a Vim que ignore los errores de algunos comandos ex precediéndolos con :silent!. Ver

:help :silent


Editar siguiendo la adición de ejemplo a la pregunta

Macro 1 y Macro 2 son recursivas y ninguna tiene ningún mecanismo explícito para terminar la recursividad. Supongo que se está disparando una de las pruebas internas de Vim para la recursividad ilimitada, lo que genera un error. Si la Macro 1 está generando dicho error, entonces ese error terminará la ejecución de la Macro de envoltura inmediatamente después @w.

Mi sugerencia sería limitar el número de veces que se ejecutan sus macros reescribiéndolas como: comandos ex y limitando el rango de líneas sobre las que se ejecutan. Por ejemplo:

qw:%s/\s\+$//^Mq
qe:%s/\n\n *}/\r}/^Mq

donde ^Msignifica escribir su tecla Intro o Retorno. No los he probado juntos en su Wrapper Macro, pero creo que podrá corregir cualquier error que haya cometido.

garyjohn
fuente
No es una sustitución en mi caso, sino un simple hallazgo (es decir, /foo). Si bien, :silent!efectivamente, el truco del submacro recursivo no abortó la macro de envoltura, ahora el submacro no termina en absoluto ... y sospecho que hacer que de alguna manera termine de nuevo también volvería a terminar la macro de envoltura. Parece que estoy atascado. : - \
DevSolar
Es difícil decir qué podría estar mal sin ver las macros que está utilizando, o un ejemplo simple que muestra el mismo problema.
garyjohn
Se agregó un ejemplo.
DevSolar
2

Lo que funcionó para mí fue una combinación de respuestas de @Peter Rincker y @garyjohn. Por separado, seguía teniendo problemas extraños.

nnoremap <leader>rt :silent! %s/\s\+$//e<CR>
let @r='\rt'
let @t=':try|silent! exe "norm! @r"|endtry|w^M'

Creo que los caracteres silent!en el <leader>rt, y el tubo entre el endtryy el wfueron las claves, simplemente tener el salto de línea después del endtryerror. Los trys trabajaron cuando yo acababa de entrar en ellos, pero cuando se ejecuta como una macro no se encontró el error sobre el texto de búsqueda mantendría a ser elevado.

Mate
fuente
1

Rutinariamente creo macros sobre la marcha cuando necesito hacer una tarea repetitiva entre muchos archivos. En mi caso, tengo NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) instalado en VIM, que crea una vsplitventana, y a la izquierda, tengo una lista de todos los archivos en El directorio actual. En un ejemplo, necesito encontrar la primera instancia de la cadena MY_TESTen el archivo y luego eliminar, si está presente, un prefijo etiquetado como CUSTOM_PREFIX-de esa línea, guardar el archivo y luego pasar a la siguiente.

Así es como hago que esta macro funcione en aproximadamente 2000 archivos en el directorio actual. Podría escribir un script bash para hacer esto, pero en mi caso es más rápido en VIM. El +denota teclas presionadas simul

# Start recording a macro sequence to register 'A'

q,a

# Search silently for the string "MY_TEST"; DO NOT report an error
# if the string could not be found.
:silent! /MY_TEST


# Replace, on just the current line, the string "CUSTOM_PREFIX-", with
# nothing (ie: delete it), and suppress any warning messages if the
# string could not be found on the current line.
:s/CUSTOM_PREFIX-//e


# Now issue some UI commands. CTRL-W then and arrow key lets you hope
# between tabs/splits/windows within vim.

CTRL+ W,

# Scroll down to the next file in the list in NERDtree



# Open the next file

ENTER

# End the macro

q

# Run the macro a thousand times in VIM

1000, @,a

¡Espero que esto ayude!

Nube
fuente