vim: Continuer la macro après une erreur dans la sous-macro?

14

Je suis en train d'embellir du code source à l'aide de vim. {1}

J'ai créé quelques macros vim qui effectuent les étapes individuelles: supprimer les espaces de fin, supprimer les lignes vides après {, supprimer les lignes vides avant {, ce genre de choses.

Maintenant, je veux créer une macro qui exécute toutes les macros individuelles dans l'ordre. Cependant, une fois la première macro récursive terminée (car elle ne trouve plus de correspondance -> erreur de correspondance), ma macro «wrapper» se termine également.

Existe-t-il un moyen de faire continuer une macro vim après qu'une sous-macro a généré une erreur?

{1} Je connais les reformatages automatiques. Je pourrais même les utiliser sur mon problème actuel. J'ai simplement mentionné le reformatage de la source dans l'intérêt de l'exemple. Ne postez aucune réponse à propos de cet embellisseur source ou de cela. La question ne concerne pas le reformatage du code en soi , mais les macros vim.

Exemple:

  • Macro 1 - découpage des espaces de fin - qw/\s\+$d$@wq
  • Macro 2 - supprimer les lignes vides avant} - qe/\n\n *}dd@eq
  • Wrapper Macro - retabbing, Macro 1, Macro 2 - qr:retab@w@eq

Lorsque @rj'exécute le wrapper - - il se retabera, puis exécutera la macro 1 jusqu'à ce qu'il n'y ait plus d'espace blanc de fin, puis se terminera ( sans exécuter la macro 2).

Clarification:

Ce que je recherche, c'est comment appeler une sous-macro pour que, lorsque cette sous-macro se termine, la macro d'appel continue?

DevSolar
la source

Réponses:

12

Je vous suggère d'utiliser :trypour "absorber" l'erreur de la sous-macro.

Voici un exemple stupide:

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

Votre macro wrapper ressemblerait à ceci:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'
Peter Rincker
la source
Bien que garyjohn fourni une solution de contournement pour ne pas avoir une erreur dans un submacro, c'est la seule réponse qui ne fait gérer une telle erreur. Je dois cependant m'excuser; Je n'ai pas vérifié votre réponse à temps pour que vous obteniez la prime (maintenant expirée) ... :-(
DevSolar
25

Si la commande défaillante est une substitution qui ne trouve pas son modèle, par exemple,

:%s/foo/bar/

quand foon'existe pas dans le tampon, vous pouvez ajouter l' eindicateur pour ignorer cette erreur, par exemple,

:%s/foo/bar/e

Voir

:help :s_flags

Vous pouvez dire à Vim d'ignorer les erreurs de certaines commandes: ex en les précédant de :silent!. Voir

:help :silent


Modifier après l'ajout d'un exemple à la question

La macro 1 et la macro 2 sont toutes deux récursives et aucune n'a de mécanisme explicite pour mettre fin à la récursivité. Je suppose que l'un des tests internes de Vim pour la récursion illimitée est déclenché, ce qui génère une erreur. Si la macro 1 génère une telle erreur, cette erreur mettra fin à l'exécution de la macro Wrapper juste après @w.

Ma suggestion serait de limiter le nombre d'exécutions de vos macros en les réécrivant en tant que: commandes ex et en limitant la plage de lignes sur lesquelles elles sont exécutées. Par exemple:

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

^Msignifie taper votre touche Entrée ou Retour. Je ne les ai pas testés ensemble dans votre macro Wrapper, mais je pense que vous pourrez corriger les erreurs que j'ai pu commettre.

garyjohn
la source
Ce n'est pas une substitution dans mon cas, mais une simple découverte (c'est-à-dire /foo). Bien :silent!que la sous-macro récursive n'ait pas abandonné la macro wrapper, la submacro ne se termine pas du tout ... et je soupçonne que le faire à nouveau se terminerait également la macro wrapper. On dirait que je suis coincé. : - \
DevSolar
Il est difficile de dire ce qui ne va pas sans voir les macros que vous utilisez ou un exemple simple qui présente le même problème.
garyjohn
Ajout d'un exemple.
DevSolar
2

Ce qui a fonctionné pour moi était une combinaison de réponses @Peter Rincker et @garyjohn. Séparément, je n'arrêtais pas d'avoir des problèmes étranges.

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

Je pense que le silent!dans le <leader>rt, et les caractères de tuyau entre le endtryet le wétaient les clés - simplement avoir la ligne coupée après l' endtryéchec. Les trys fonctionnaient quand je venais de les entrer, mais quand ils étaient exécutés en tant que macro, l'erreur sur le texte de recherche était introuvable continuerait d'être soulevée.

Mat
la source
1

Je crée régulièrement des macros à la volée lorsque je dois effectuer une tâche répétitive parmi de nombreux fichiers. Dans mon cas, j'ai NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) installé dans VIM, qui crée une vsplitfenêtre, et à gauche, j'ai une liste de tous les fichiers dans le répertoire courant. Dans un exemple, je dois trouver la première instance de la chaîne MY_TESTdans le fichier, puis supprimer, s'il est présent, un préfixe étiqueté à CUSTOM_PREFIX-partir de cette ligne, enregistrer le fichier, puis passer à la suivante.

Voici comment faire fonctionner cette macro sur environ 2000 fichiers dans le répertoire courant. Je pourrais écrire un script bash pour ce faire, mais c'est plus rapide dans VIM, dans mon cas. Le +indique que les touches sont enfoncées simultanément

# 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

J'espère que cela t'aides!

Nuage
la source