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 :
!
: filtrer la sélection par la commande qui va suivrei
: innerp
: paragraphesh
: la commande par laquelle on va filtrer, ici dash
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
| pokkpkContrairement à 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.