vim: continua macro dopo errore in submacro?


14

Sto per abbellire un po 'di codice sorgente usando vim. {1}

Ho creato un paio di macro vim che eseguono i singoli passaggi: rimozione di spazi vuoti finali, rimozione di righe vuote dopo {, rimozione di righe vuote prima {, quel tipo di cose.

Ora, voglio creare una macro che esegue tutte le singole macro in sequenza. Tuttavia, una volta terminata la prima macro ricorsiva (poiché non riesce più a trovare alcuna corrispondenza -> errore di corrispondenza), termina anche la mia macro "wrapper".

C'è un modo per far continuare una macro vim dopo che un submacro ha generato un errore?

{1} Io so circa reformatters automatici. Potrei persino usarli sul mio problema attuale. Ho semplicemente citato la riformattazione della fonte per il bene dell'esempio. Non pubblicare alcuna risposta su questo estetista o quello. La domanda non riguarda la riformattazione del codice in , ma le macro di VIM.

Esempio:

  • Macro 1 - rifilatura degli spazi bianchi finali - qw/\s\+$d$@wq
  • Macro 2 - eliminazione di righe vuote prima} - qe/\n\n *}dd@eq
  • Wrapper Macro - retabbing, Macro 1, Macro 2 - qr:retab@w@eq

Quando eseguo il wrapper - @r- eseguirà il retab, quindi eseguirà la Macro 1 fino a quando non viene trovato più spazio vuoto finale, quindi termina ( senza eseguire la Macro 2).

Una precisazione:

Quello che sto cercando è come chiamare un submacro in modo che quando termina quel submacro, la macro chiamante continua?

Risposte:


12

Ti suggerisco di usare :tryper "assorbire" l'errore del submacro.

Ecco un esempio sciocco:

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

La macro del wrapper sarebbe simile a questa:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'

Mentre garyjohn ha fornito una soluzione alternativa per non avere un errore in un submacro, questa è l'unica risposta che in realtà gestisce un errore del genere. Devo scusarmi però; Non ho verificato la tua risposta in tempo perché tu
potessi

25

Se il comando non riuscito è una sostituzione che non trova il suo schema, ad es.

:%s/foo/bar/

quando foonon esiste nel buffer, è possibile aggiungere il eflag per ignorare quell'errore, ad es.

:%s/foo/bar/e

Vedere

:help :s_flags

Puoi dire a Vim di ignorare gli errori di alcuni comandi: ex precedendoli con :silent!. Vedere

:help :silent


Modifica in seguito all'aggiunta dell'esempio alla domanda

Macro 1 e Macro 2 sono entrambe ricorsive e non hanno alcun meccanismo esplicito per terminare la ricorsione. La mia ipotesi è che venga attivato uno dei test interni di Vim per la ricorsione illimitata, che genera un errore. Se la Macro 1 sta generando un tale errore, quell'errore interromperà immediatamente l'esecuzione della Macro wrapper @w.

Il mio suggerimento sarebbe di limitare il numero di volte in cui le tue macro vengono eseguite riscrivendole come: comandi ex e limitando l'intervallo di linee su cui vengono eseguite. Per esempio:

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

dove ^Msignifica digitare il tasto Invio o A capo. Non li ho testati insieme nel tuo Wrapper Macro, ma penso che sarai in grado di correggere eventuali errori che potrei aver fatto.


Non è una sostituzione nel mio caso, ma una semplice scoperta (cioè, /foo). Mentre in :silent!effetti il ​​trucco del submacro ricorsivo non ha interrotto la macro wrapper, ora il submacro non si interrompe affatto ... e sospetto che farlo in qualche modo terminare di nuovo terminerebbe di nuovo anche la macro wrapper. Sembra che sono bloccato. : - \
DevSolar il

È difficile dire cosa potrebbe esserci di sbagliato senza vedere le macro che stai utilizzando o un semplice esempio che presenta lo stesso problema.
garyjohn,

Aggiunto un esempio.
DevSolar,

2

Ciò che ha funzionato per me è stata una combinazione di risposte @Peter Rincker e @garyjohn. Separatamente continuavo a ricevere strani problemi.

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

Penso che i caratteri silent!in <leader>rt, e pipe tra il endtrye il wfossero i tasti - semplicemente avendo la linea interrotta dopo il endtryfallimento. Gli trys funzionavano quando li inserivo, ma quando venivano eseguiti come macro l'errore sul testo di ricerca non veniva trovato continuava a essere sollevato.


1

Di solito creo macro al volo quando devo svolgere un'attività ripetitiva tra molti file. Nel mio caso, ho NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) installato in VIM, che crea una vsplitfinestra e, a sinistra, ho un elenco di tutti i file in la directory corrente. In un esempio, devo trovare la prima istanza della stringa MY_TESTnel file e quindi eliminare, se presente, un prefisso etichettato come CUSTOM_PREFIX-da quella linea, salvare il file, quindi passare al successivo.

Ecco come faccio a far funzionare questa macro su circa 2000 file nella directory corrente. Potrei scrivere uno script bash per farlo, ma nel mio caso è più veloce in VIM. I +tasti indicano che i tasti vengono premuti 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

Spero che sia di aiuto!

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.