Des macros utiles pour faire du shell dans vim

Retour accueil


Exécuter du code dans vim

J’écris souvent du shell dans vim et j’ai fréquemment envie de vérifier ce que donnerait la commande que je suis en train d’écrire.

Admettons que j’ai le code suivant :

seq 5 |
    sed 's/^/(/;s/$/+2)/' |
    paste -s -d'*' |
    bc

et que je veuille vérifier le résultat dans vim. Je peux faire dans vim !ip puis taper sh et obtenir dans mon buffer le résultat 2520.

Déconstruisons la commande :

On pourrait dire qu’en français ! est une sorte de verbe, ce que l’on veut faire (filtrer) et ip une sorte de COD, ce sur qu’on on va le faire (le inner paragraphe).

“Inner” paragraphe veut dire ça :

| azdazd
| pokkpk

Contrairement à l’inverse, qui serait la totalité d’un paragraphe, autrement dit “a paragraph” et dont le raccourci est a :

|
| azdazd
| pokkpk
|

La macro

Maintenant imaginons que l’on veuille conserver la commande sous les yeux et avoir le résultat en dessous. Ça peut être utile pour écrire une regex un peu complexe avec le texte sous les yeux ou ne pas avoir à faire u (ctrl+z) à chaque fois pour éditer la commande.

Pour faire cela j’ai créé la macro suivante :

map <F2> mzyip}o<CR><ESC>P!ipsh<CR>`z

qui copie le paragraphe en dessous et l’exécute de façon à conserver la copie originale et renvoyer le curseur à la ligne où l’on était en lançant la macro de façon à pouvoir reprendre l’édition. Pour changer la touche sur laquelle appuyer pour la lancer il faut modifier <F2>. Si vous voulez filtrer avec autre chose vous pouvez modifier sh pour python3 par exemple. Je pense que cette macro est un peu cracra parce que je ne sais pas bien les écrire. Si vous voulez me proposer la votre pour le même besoin c’est avec plaisir.

Une macro inspirée de celle-ci qui donne le résultat d’une commande jusqu’à la ligne courante et non pas du paragraphe entier pourrait s’écrire comme ceci :

map <F5> mzV{y}o<CR><ESC>P}k$x!ipsh<CR>`z

Elle m’est utile quand je débug une longue commande avec beaucoup de pipe écrit sur des lignes différentes. Utile aussi pour les enseigner et montrer facilement la tête des données à chaque étape de la commande.

Limites

Les deux ne gèrent pas très bien (et pas de la même manière) l’existence ou non d’une ligne vide suivant le paragraphe courant. Aussi, elles ne servent que pour tester une ou des commandes qui se tiennent en un paragraphe. Pour tester un ensemble plus large soit on le fait comme au début de l’article “à la main” à l’aide des déplacements ou après une sélection visuelle, soit on ne saute pas de ligne entre l’ensemble de commandes. Par exemple :

set machin bidule
greet () {
    echo "Hello $1 $2"
}
greet $1 $2

donnera

Hello machin bidule

et on pourra ajouter les sauts de lignes entre la fonction et la commandes au dessus et en dessous après le test.

Ces macros me sont souvent utiles parce que j’ai tendance à écrire de longues commandes sous la forme :

cmd 1 |
    cmd 2 |
    cmd 3 |
    cmd 4 | cmd 5 |
    cmd 6

et à vouloir les tester indépendamment les une des autres au sein d’un script. Si ce n’est pas votre façon de travailler elles vous seront d’une utilité marginale.