Le site arthur.bebou.netlib.re - retour accueil
Anonyme, en lecture seule : git clone git://bebou.netlib.re/arthur.bebou
Authentifié·e, en écriture : git clone ssh://git@bebou.netlib.re:1459/srv/git/arthur.bebou
Log | Files | Refs | zip | tar.gz |
index.sh (10400B)
1 #! page
2 title: Évaluer ses scripts en temps réel
3 author: Arthur Pons
4 description: Il est parfois fatiguant de faire l\'aller retour entre l\'écriture d\'une commande et son exécution. Créons, avec vim et/ou tmux des environnements permettant de fondre les deux
5 publication: 2024-05-09
6
7 sectionmd: main
8
9 > ATTENTION : Ce script est vraiment dangereux, ne l'utilisez pas si vous ne
10 > savez pas ce que vous faîtes. N'écrivez jamais de script contenant `rm` avec.
11 > Si vous écrivez une commande qui lit dans stdin il faudra le fermer en insérant
12 > un caractère de fin de fichier, en sortant du mode inserstion, en réinsérant un
13 > caractère de fin de fichier puis finalement en supprimant la commande qui pose
14 > souci. Vous êtes prévenu·es, c'est expérimental est tout cassé.
15
16 ## Objectif
17
18 L'objectif est d'avoir, l'un à côté de l'autre, un script et ses sorties STDERR
19 et STDOUT, en temps réel avec une mise à jour à chaque fois que l'on modifie le
20 script. Une interface comme celle-ci devrait permettre de faciliter l'écriture
21 de scripts dont la sortie nous intéresse, typiquement lorsqu'il faut traiter du
22 texte et quand itérer souvent et rapidement est souhaitable[^1]. Elle pourrait
23 également être un bon outil pour l'enseignement de `sed`, `awk`, `paste`, `cut`,
24 `tr` et toute la bande que j'aime bien.
25
26 Il n'est pas question ici d'analyser les actions du script et d'afficher en
27 français les impacts qu'il a eu sur le système (création/suppression de fichier
28 etc). Il est question de faciliter l'écriture d'une commande `sed` un peu
29 dantesque sans avoir à systématiquement exécuter le script à la main.
30
31 L'idée me vient de
32 [fzrepl](https://github.com/DanielFGray/fzf-scripts/blob/master/fzrepl) de
33 Daniel F Gray. Je voulais quelque chose de similaire mais qui fonctionne
34 pour une quantité arbitraire de commandes et éditable dans vim.
35
36 Au passage je découvre sans l'avoir prévu que ce système me permet de résoudre
37 d'une manière bien plus puissante qu'auparavant un problème que j'avais documenté
38 dans ce [vieil article](/benchmarkcatium/#et-alors-), section :
39 "L’utilisation d’éditeurs de texte s’interfaçant bien avec le système permet de
40 tester des bouts de markdown". En effet, si j'ouvre l'un des fichiers sources
41 de ce site avec la configuration vim qui va suivre j'obtiens automatiquement le
42 résultat html dans la fenêtre droite.
43
44 ## Implémentation
45
46 J'ai pour le moment la flemme de gérer les arguments de façon à faire des
47 choses différentes selon si on passe un argument un script déjà existant ou
48 pas, selon si le chemin est absolu ou relatif etc. Les scripts tels que
49 présentés en dessous vont donc systématiquement tout créer en tant que fichier
50 temporaire. Si à la fin de votre expérimentation vous voulez sauvegarder le
51 script vous pouvez toujours lancer `:w votre_script.sh`.
52
53 ### Avec vim tout seul
54
55 Commençons d'abord par créer les fichiers qui vont contenir le script et sa
56 sortie et rendre le script exécutable :
57
58 script=$(mktemp)
59 data=$(mktemp)
60 chmod +x "$script"
61
62 Vient ensuite l'ouverture de vim et sa configuration :
63
64 vim -c "set autowrite"\
65 -c "autocmd TextChanged * silent! !$script > $data 2>&1"\
66 -c "autocmd TextChangedI * silent! !$script > $data 2>&1"\
67 -c "vnew $data"\
68 -c "set updatetime=100 | set autoread | autocommand CursorHoldI * checktime | autocommand CursorHold * checktime"\
69 -c "wincmd h | doautocmd TextChanged"\
70 "$script"
71
72 Vim est appelé avec tout un tas de commandes suivant l'option `-c` qui
73 s'exécuteront automatiquement au lancement. Le denier argument est le chemin
74 vers le script.
75
76 Expliquons chacune des commandes vim :
77
78 * `set aw` : le fichier sera automatiquement écrit à chaque fois qu'une
79 commande externe sera lancée
80 * `autocmd TextChanged * silent! !$script > $data 2>&1` : A chaque fois que
81 le texte change en mode normal on exécute, en ignorant sa sortie et ses
82 erreurs éventuelles (`silent!`), le script dont on redirige tout vers le
83 fichier de sortie
84 * Idem mais en mode insertion
85 * `vnew $data` : on ouvre une fenêtre verticale avec le fichier de sortie
86 * `set updatetime=100 | set autoread | autocommand CursorHoldI * checktime |
87 autocommand CursorHold * checktime` : On modifie l'intervalle de mise à jour
88 à 100ms, on met le buffer avec e fichier de sortie en lecture automatique
89 (il se rafraichit à chaque changement), on force l'exécution de `checktime`
90 à chaque première fois que le curseur ne bouge plus pendant 100ms après
91 qu'il a bougé
92 * `wincmd h | doautocmd TextChanged` : on revient sur la fenêtre avec le
93 script et on déclenche une première fois l'un des évènements pour peupler
94 le fichier de sortie (utile si l'on ouvre un script déjà existant)
95
96 Finalement on affiche les chemins des deux fichiers temporaire quand on ferme
97 vim au cas-où l'on en est besoin :
98
99 echo "script : $script"
100 echo "données : $data"
101
102 Les avantages de cette version sont de ne pas dépendre de watch ni de tmux et
103 de pouvoir parcourir la sortie dans un buffer vim avec tout ce que cela
104 implique comme possibilité.
105
106 ### Avec vim + tmux + watch
107
108 Les dépendances sont :
109
110 * Une version relativement à jour de vim (qui a les évènements `TextChanged*`)
111 * tmux
112 * watch
113
114 On commence de la même manière :
115
116 script=$(mktemp)
117 data=$(mktemp)
118 chmod +x "$script"
119
120 Puis on crée la session tmux :
121
122 tmux new \
123 vim -c "set aw"\
124 -c "autocmd TextChanged * silent! !$script > $data 2>&1"\
125 -c "autocmd TextChangedI * silent! !$script > $data 2>&1"\
126 -c "doautocmd TextChanged"\
127 "$script"\
128 \; split-window -h "watch -c -d -t -n 0.1 cat $data" \; select-pane -L
129
130 Finalement on affiche les chemins en sortie de session :
131
132 echo "script : $script"
133 echo "données : $data"
134
135 Les avantages sont de ne pas avoir à utiliser le hack vim un peu étrange à base
136 de CursorHold pour que tout soit à jour, de voir ce qui a été modifié en sortie
137 à l'aide de `-d` de watch et être directement déposé dans tmux ce qui peut se
138 révéler utile pour retrouver votre travail plus tard. Évidemment ce dernier
139 point n'est pas essentiel si vous avez de toute façon l'habitude d'être dans
140 une session tmux quoi qu'il arrive.
141
142 ## L'espace entre les CLI des années 80 et les GUI
143
144 Au delà des raisons évoquées [en intro](/liverepl/#objectif) j'ai une autre
145 motivation à écrire ce genre d'outils.
146
147 De nombreuses critiques sont formulées envers les interfaces en ligne de
148 commande. Même si je pense qu'elles sont parfois injustes et le fruit d'apriori
149 culturels et techniques plus que de réelles limitations qui seraient par
150 ailleurs inexistantes dans les autres formes d'interfaces, il convient
151 d'admettre que l'expérience initiale dans un terminal linux est aride.
152 [Aurélien Tabard](https://tabard.fr/) en résume bien les principales raisons :
153
154 > Si la découvrabilité est en effet un point important, la gestion des erreurs
155 > l'est tout autant. Le undo n'est pas tellement développé dans les cli, pourtant
156 > la capacité d'essai-erreur-correction est facteur d'apprentissage important
157 > (oui il y a des façons de se tromper élégamment dans un terminal, mais le jour
158 > ou tu te trompes pour une raison ou une autre, le undo n'est pas là). D'autre
159 > notions permettent comme celles de gouffre d'évaluation et d'exécution peuvent
160 > expliquer le succès des gui. Enfin la capacité des systèmes à communiquer sur
161 > ce qu'ils permettent de faire (voir [par exemple ce
162 > papier](http://jovermeulen.com/Research/FeedforwardCHI2013) sur les
163 > affordances percues et le feedforward) est peu présente dans les cli.
164
165 De fait beaucoup de personnes sont introduites aux cli via des cours, des
166 tutos, des outils ne cherchant pas à faciliter l'apprentissage et l'usage des
167 cli et tombant la tête la première dans chacun des points soulevés par
168 Aurélien. Personnellement j'ai fait mes premières années de shell en école
169 d'ingénieur sans jamais savoir que l'on pouvait chercher dans l'historique des
170 commandes avec `ctrl+r`, que beaucoup de commandes avaient des options pour
171 lister ce qu'elles allaient faire avant de les faire, que l'on pouvait mettre
172 beaucoup de couleurs dans les terminaux modernes, que l'existence des TUI
173 implique que l'on puisse faire des choses comme fzy, qu'il existait des shells
174 moins complexes que bash et avec une super auto-complétion pour un large
175 ensemble de commande ou une simple liste, même un peu indigeste, des commandes
176 généralement disponibles sur un Unix. J'ai le sentiment que la conséquence de
177 cela est que de nombreuses personnes, même dans le métier, n'ont qu'une vision
178 très limitée de ce que peuvent les cli et a fortiori des TUI qui fonctionnent
179 dans un terminal. Il est donc naturel que la plupart des personnes perçoivent
180 ces interfaces comme bloquées dans les années 70/80 et ne s'y tournent que pour
181 les usages à raison catalogués comme les plus appropriés. Et pourtant on peut
182 y mener la majorité de sa vie numérique.
183
184 Attention, contrairement à l'impression que j'ai trop souvent donné lorsque je
185 parle de ce sujet, l'idée n'est pas de tout faire dans un terminal simplement
186 parce que je kiffe le terminal. C'est parce que l'usage de GUI modernes me
187 pousse à changer mon matériel, à mettre de la distance entre les personnes qui
188 produisent les logiciels que j'utilise et moi et à cloisonner mes logiciels
189 plutôt que de les faire causer entre eux que je m'intéresse à autre chose. Ne
190 sachant pas où me tourner pour trouver une communauté et une culture
191 ingénieurale axées sur le développement de GUI sobres, interopérables et
192 techniquement simples, je me tourne vers une communauté et une culture qui, la
193 plupart du temps, regroupe toutes ces qualités, j'ai nommé celle des personnes
194 qui vivent dans un terminal Unix.
195
196 Je cherche donc, avec des outils comme celui décrit dans cet article, à montrer
197 qu'il existe un espace entre les GUI d'aujourd'hui et les CLI des années 80
198 dans lequel on peut aborder les points soulevés par Aurélien tout en profitant
199 des propriétés techniques plus avantageuses pour la sobriété de nos usages du
200 numérique.
201
202 [^1]: typiquement l'écriture d'une regex un peu complexe d'où le succès d'interfaces type [regex101](https://regex101.com/)