vim: Makro nach Fehler in Submacro fortsetzen?

14

Ich bin gerade dabei, Quellcode mit vim zu verschönern. {1}

Ich habe ein paar vim-Makros erstellt, die die einzelnen Schritte ausführen: Entfernen von nachgestellten Leerzeichen, Entfernen von Leerzeilen danach {, Entfernen von Leerzeilen davor {, solche Dinge .

Jetzt möchte ich ein Makro erstellen, das alle einzelnen Makros nacheinander ausführt. Sobald das erste rekursive Makro beendet wird (da es keine Übereinstimmungen mehr findet -> Übereinstimmungsfehler), wird auch mein "Wrapper" -Makro beendet.

Gibt es eine Möglichkeit, ein vim-Makro fortzusetzen, nachdem ein Submacro einen Fehler generiert hat?

{1} Ich kenne automatische Reformatierer. Ich könnte sie sogar für mein aktuelles Problem verwenden. Ich habe lediglich die Neuformatierung der Quelle erwähnt, um das Beispiel zu verdeutlichen. Veröffentlichen Sie keine Antworten zu diesem oder jenem Quellverschönerer. Die Frage ist nicht über Code Neuformatierung per se , sondern um vim Makros.

Beispiel:

  • Makro 1 - abschließendes Leerzeichen entfernen - qw/\s\+$d$@wq
  • Makro 2 - Löschen von Leerzeilen vor} - qe/\n\n *}dd@eq
  • Wrapper Macro - Retabbing, Macro 1, Macro 2 - qr:retab@w@eq

Wenn ich den Wrapper ausführe @r, wird er retabiert, dann wird Makro 1 ausgeführt, bis kein abschließendes Leerzeichen mehr gefunden wird, und dann wird beendet ( ohne Makro 2 auszuführen).

Klärung:

Nach was ich suche, ist, wie man ein Submacro aufruft, damit, wenn dieses Submacro beendet wird, das aufrufende Makro fortfährt?

DevSolar
quelle

Antworten:

12

Ich schlage vor, Sie verwenden :try, um den Fehler des Submakros zu "absorbieren".

Hier ist ein dummes Beispiel:

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

Ihr Wrapper-Makro würde ungefähr so ​​aussehen:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'
Peter Rincker
quelle
Während garyjohn eine Abhilfe bereitgestellt für nicht mit einen Fehler in einem submacro, ist dies die einzige Antwort , die eigentlich nicht behandeln einen solchen Fehler. Ich muss mich allerdings entschuldigen. Ich habe Ihre Antwort nicht rechtzeitig überprüft, damit Sie die (jetzt abgelaufene) Prämie erhalten ... :-(
DevSolar
25

Wenn der fehlgeschlagene Befehl eine Substitution ist, deren Muster nicht gefunden wird, z.

:%s/foo/bar/

Wenn fooder Puffer nicht vorhanden ist, können Sie das eFlag hinzufügen , um diesen Fehler zu ignorieren. Beispiel:

:%s/foo/bar/e

Sehen

:help :s_flags

Sie können Vim anweisen, die Fehler einiger: ex-Befehle zu ignorieren, indem Sie ihnen Folgendes voranstellen :silent!. Sehen

:help :silent


Bearbeiten Sie nach dem Hinzufügen eines Beispiels zur Frage

Makro 1 und Makro 2 sind beide rekursiv und haben keinen expliziten Mechanismus zum Beenden der Rekursion. Ich vermute, dass einer von Vims internen Tests auf unbegrenzte Rekursion ausgelöst wird, was einen Fehler erzeugt. Wenn Makro 1 einen solchen Fehler generiert, wird die Ausführung des Wrapper-Makros unmittelbar danach durch diesen Fehler abgebrochen @w.

Mein Vorschlag wäre, die Anzahl der ausgeführten Makros zu begrenzen, indem Sie sie wie folgt umschreiben: ex-Befehle und den Zeilenbereich einschränken, über den sie ausgeführt werden. Beispielsweise:

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

Wo ^Mbedeutet die Eingabe Ihrer Eingabetaste oder Return-Taste. Ich habe diese in Ihrem Wrapper-Makro nicht zusammen getestet, aber ich denke, Sie können alle Fehler beheben, die ich möglicherweise gemacht habe.

garyjohn
quelle
Es ist kein Ersatz in meinem Fall, aber ein einfacher Fund (dh /foo). Zwar :silent!hat der Trick des rekursiven Submakros das Wrapper-Makro nicht abgebrochen, aber jetzt wird das Submakro überhaupt nicht beendet. Scheint, als würde ich stecken bleiben. : - \
DevSolar
Es ist schwierig zu sagen, was falsch sein könnte, ohne die von Ihnen verwendeten Makros oder ein einfaches Beispiel zu sehen, das das gleiche Problem aufweist.
Garyjohn
Beispiel hinzugefügt.
DevSolar
2

Was für mich funktioniert hat, war eine Kombination aus @Peter Rincker und @garyjohn Antworten. Separat bekam ich immer wieder seltsame Probleme.

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

Ich denke, die silent!in der <leader>rt, und die Pipe-Zeichen zwischen endtryund wwaren die Schlüssel - einfach mit dem Zeilenumbruch nach dem endtryfehlgeschlagenen. Das trys hat funktioniert, als ich sie gerade eingegeben habe, aber wenn es als Makro ausgeführt wurde, wurde der Fehler bezüglich des Suchtexts nicht gefunden.

Matt
quelle
1

Ich erstelle regelmäßig Makros, wenn ich eine sich wiederholende Aufgabe in vielen Dateien ausführen muss. In meinem Fall habe ich NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) in VIM installiert, wodurch ein vsplitFenster erstellt wird, und auf der linken Seite habe ich eine Liste aller Dateien in das aktuelle Verzeichnis. In einem Beispiel muss ich die erste Instanz der Zeichenfolge MY_TESTin der Datei suchen und dann, falls vorhanden, ein Präfix löschen, das als CUSTOM_PREFIX-aus dieser Zeile beschriftet ist, die Datei speichern und dann mit der nächsten fortfahren.

Hier ist, wie ich dieses Makro auf etwa 2000 Dateien im aktuellen Verzeichnis arbeiten lassen. Ich könnte ein Bash-Skript schreiben, um dies zu tun, aber in meinem Fall ist es in VIM schneller. Die +Tasten werden gleichzeitig gedrückt

# 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

Hoffe das hilft!

Wolke
quelle