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 (24781B)
1 #! page
2 title: Améliorer la découvrabilité des CLI : l\'auto-complétion
3 author: Arthur Pons
4 description: Les CLI sont peu découvrables. Voyons comment écrire de l\'auto-complétion custom pour améliorer tout ça avec l\'exemple de tricount
5 publication: 2026-05-29
6
7 section: main
8
9 ## Le problème
10
11 Très rapidement : les outils en ligne de commande sont peu découvrables. On
12 tape une commande puis quoi ?
13
14 
16
17 On lit le manuel GNU de ses morts ? On tente peut-être un `-h` ou un `--help`
18 qui listera un sous-ensemble des options sans trop d'explications, ou au
19 contraire, imprimera la bible toute entière[^1] ? Si l'outil est pas trop
20 compliqué, mettons `mv`, c'est jouable. Et encore, il faut savoir que `man mv`
21 existe, désepérer du fait que ce soit un manuel de *référence*, éventuellement
22 savoir que `info mv` existe, probablement plutôt aller voir des tutos sur
23 internet et se rendre compte que, puisque l'on est en 2026, la plupart sont
24 générés par IA. Bref pas facile.
25
26 Une solution pourrait être de faire de l'auto-complétion. Grâce à la magie de ce
27 qu'il se passe lorsqu'on appuie sur la touche tabulation en écrivant une
28 commande dans un shell moderne[^2] le shell peut nous indiquer ce qu'il est
29 possible d'écrire à cet endroit de la commande.
30
31 J'ai trouvé très peu de tutoriels satisfaisant sur la question donc j'en écris
32 un :)
33
34 ## Les limites
35
36 Dans cet article je partage ce que j'ai appris en écrivant l'auto-complétion
37 `zsh` pour l'outil [`tricount`](http://git.bebou.netlib.re/tricount). Il en
38 découle :
39
40 * qu'il ne couvre pas l'auto-complétion `bash` (mais j'ai cru comprendre que
41 c'était similaire)
42 * que l'on ne parle pas de découvrabilité lorsque l'on ne sait même pas quelle
43 commande taper (voir plutôt [zenu](http://arthur.bebou.netlib.re/zenu) pour
44 ça)
45 * que ce n'est pas un tutoriel complet sur l'auto-complétion `zsh` mais
46 uniquement ce dont j'ai eu besoin pour `tricount`.
47
48 Par ailleurs j'émets l'hypothèse que l'auto-complétion est significativement
49 utile pour la découvrabilité d'une commande mais je ne l'ai pas réellement
50 testé. Pour pouvoir réellement mesurer l'intérêt de l'auto-complétion pour la
51 découvrabilité il faudrait que je le fasse tester à des copaines sans et avec
52 l'auto-complétion mais on est pas ici pour faire de la recherche lol 🤓
53
54 ## Le résultat
55
56 L'objectif est de passer de ça :
57
58 <video src="sans-auto.mp4" controls loop muted loading=lazy>
59
60 à ça (vidéo de 500Ko, cliquez dessus pour lancer) :
61
62 <video src="avec-auto.mp4" preload=none controls muted loading=lazy>
63
64 On remarquera que l'outil fonctionne avec une syntaxe de *commande*,
65 *sous-commande* et *objet*. Les *sous-commandes* et *objets* disponibles
66 dépendent de la *commande* choisie. Par exemple la commande *creer* ne
67 nécessite rien d'autre mais si l'on choisit la commande *ajouter* il
68 faudra ensuite choisir un *objet* entre *dépense* et *personne*. Si l'objet est
69 *dépense* il faudra choisir le nom d'une personne puis un montant etc.
70
71 Ce qui rend l'auto-complétion vraiment utile est qu'elle est entièrement
72 *contextuelle*. C'est ce que fait par exemple l'auto-complétion `zsh` de la
73 commande `sed`. L'auto-complétion sait si l'on est en position d'écrire une
74 nouvelle commande (ici `s///`) ou d'apporter une modification à une commande `s`
75 (`g` et `i` par exemple) :
76
77 <video src="sed-auto.mp4" controls loop loading=lazy>
78
79 ## Le code
80
81 ### La base, `compadd`
82
83 L'auto-complétion de `zsh` repose sur des fonctions d'auto-complétion[^9]. Ces
84 fonctions sont des fonctions shell classiques appelées à chaque fois que
85 l'utilisateurice appuie sur la touche tabulation[^4]. Elles commencent
86 habituellement par un `_` et il est apparemment conventionnel de les nommer
87 du nom de la commande qu'elles complètent bien que ce ne soit pas obligatoire.
88 Imaginons donc une fonction de complétion tout à fait inutile affichant `a`,
89 destinée à compléter la commande `a`[^5] :
90
91 ```
92 _a(){ printf "a"; }
93 ```
94
95 Pour l'associer à la commande `a` (inexistante mais c'est accessoire pour le
96 moment) il existe une commande `compdef` qui prend en argument le nom d'une
97 fonction puis le nom de la commande qu'elle doit compléter :
98
99 ```
100 compdef _a a
101 ```
102
103 Pour vérifier le résultat il suffit d'initier une commande `a`, de mettre un
104 espace puis d'appuyer sur tabulation :
105
106 <video src="a-auto.mp4" controls loop loading=lazy>
107
108 C'est très bien mais ça ne permet pas l'auto-complétion. Pour programmer ce que
109 l'on souhaite, c'est à dire la sélection des options et arguments parmi un
110 ensemble restreint il faut utiliser une seconde fonction `zsh`, `compadd`[^6].
111
112 Dans sa forme la plus simple `compadd` s'utilise en lui passant en argument
113 les "candidats" à l'auto-complétion. Si l'on ajoute `1234`, `5678` et `91011`
114 alors ces trois chaînes seront proposées à l'auto-complétion via un petit menu
115 s'affichant en dessous de la ligne de commande en cours et navigable avec les
116 flèches. On verra [plus
117 tard](/auto-completion/#dcorrler-laffichage-des-candidats-de-largument-auto-complt-avec--ld)
118 qu'il est possible de modifier l'affichage de ce menu pour par exemple donner
119 des informations à propos des candidats.
120
121 Si l'on commence à écrire un argument et que le début match avec l'un de ces
122 candidats de manière non ambiguë, l'auto-complétion l'ajoutera automatiquement :
123
124 <video src="compadd-auto.mp4" controls loop loading=lazy>
125
126 Puisque la fonction dans laquelle on l'écrit est une fonction shell
127 classique on peut entourer les `compadd` de toute la logique nécessaire pour
128 trouver les bons candidats et les afficher au bon moment[^10]. Reste alors à
129 connaître les différentes options pratiques de `compadd` et les variables
130 disponibles pour connaitre l'état de la commande en cours d'écriture.
131
132 ### Ses options
133
134 #### Afficher des message d'information ou d'erreurs
135
136 Pour ajouter un texte explicatif avant les candidats on peut utiliser l'option
137 `-X` ou `-x` de `compadd`. `-X` s'affichera uniquement s'il existe des candidats,
138 `-x` s'affichera quoi qu'il arrive. `-x` est donc assez utile pour afficher des
139 messages "d'erreurs". Ainsi dans la vidéo suivante on utilise `-X` pour
140 afficher le message "Choisir une personne à retirer" mais `-x` pour afficher
141 "Personne à retirer" :
142
143 <video src="compadd2-auto.mp4" controls loop loading=lazy>
144
145 #### Auto-compléter plusieurs candidats d'un coup avec `-Q`
146
147 Il peut être utile qu'un unique candidat soit lui même la concaténation de
148 plusieurs arguments. Disons par exemple qu'à un état de l'auto-complétion on
149 veuille faire exécuter la sous-commande "cmd1" suivi de la sous-sous-commande
150 "cmd2" à l'utilisateurice. Si l'on ajoute naïvement la chaîne "cmd1 cmd2" en
151 candidat le système le considère en un seul bloc et échappe l'espace entre les
152 deux :
153
154 ```
155 a cmd1\ cmd2
156 ```
157
158 Pour y remédier il faut utiliser l'option `-Q` :
159
160 ```
161 compadd -Q "cmd1 cmd2"
162 ```
163
164 Qui auto-complètera :
165
166 ```
167 a cmd1 cmd2
168 ```
169
170 A l'éxécution la commande `a` comprendra bien `cmd1` et `cmd2` comme deux
171 arguments différents.
172
173 Cette astuce est utilisée au tout début de la vidéo du résultat pour
174 automatiquement ajouter `nom-bdd creer` en l'absence de bdd existante.
175
176 #### Ne pas trier automatiquement les candidats avec `-J arg -o nosort`
177
178 Par défaut le système d'auto-complétion trie les candidats par ordre
179 alphabétique. Si ce n'est pas souhaitable et qu'on veut les afficher dans
180 l'ordre fourni à `compadd` il faut associer l'option `-o nosort` avec l'option
181 `-J` qui prend un argument. `-o` ne fonctionne pas seul, il faut créer un
182 "groupe" de candidat avec l'option `-J` en écrivant, par exemple, `-J a`. Je
183 n'ai pas eu besoin d'utiliser les groupes de candidats donc je n'en sais pas
184 plus.
185
186 Avec la commande `compadd -J a -o nosort b c a` le système nous proposera les
187 candidats dans l'ordre `b c a` plutôt que `a b c`.
188
189 #### Décorréler l'affichage des candidats de l'argument auto-complété avec `-ld`
190
191 Par défaut ce qui s'affichage dans le menu d'auto-complétion est identique à la
192 valeur des candidats. Si l'on a pour candidats `a b c` le mnu proposera `a b c`
193 et notre choix complètera `a`, `b` ou `c`.
194
195 Il est parfois utile de décorréler ce qui est affiché dans le menu de choix et
196 ce qui est réellement complété. Pour cela il faut associer les options
197 `-l` et `-d`. `-l` demande à ce qu'un seul candidat soit affiché par ligne et
198 `-d` permet de renseigner un tableau de valeurs séparées par des espaces. Le
199 système va associer une à une les valeurs de ce tableau et les candidats qu'il a
200 récupéré en argument de `compadd`. Le menu de choix affichera visuellement le
201 contenu du tableau `-d` mais ce sera les candidats associés qui seront ajoutés
202 dans la ligne de commande. Ainsi avec le tableau et l'appel à `compadd` suivants :
203
204 ```
205 desc="(
206 creer\ \ \ \ --\ Créer\ une\ nouvelle\ base\ de\ donnée
207 ajouter\ \ --\ Ajouter\ une\ dépense\ ou\ une\ personne
208 retirer\ \ --\ Retirer\ une\ dépense\ ou\ une\ personne
209 lister\ \ \ --\ Afficher\ le\ contenu\ de\ la\ bdd
210 calculer\ --\ Calculer\ qui\ doit\ combien\ à\ qui
211 )"
212
213 compadd -J a -o nosort -ld $desc creer ajouter retirer lister calculer
214 ```
215
216 Le système proposera visuellement l'option `creer -- Créer une nouvelle base
217 de donnée` pour le candidat `creer` et ainsi de suite. Puisque les éléments du
218 tableau du menu de choix sont séparés par des esapces il faut bien en échapper
219 les espaces.
220
221 Cette technique est utilisée à deux reprises dans la vidéo du résultat, d'abord
222 pour les commandes vues dans l'exemple ici, ensuite pour sélectionner la dépense
223 à retirer (l'utilisateurice navigue dans la bdd ligne par ligne mais uniquement
224 l'identifiant de la dépense est auto-complété).
225
226 #### Ne pas supprimer les candidats doublons avec `-2`
227
228 Par défaut le système supprime les candidats doublons. Si l'on fait `compadd 1 1
229 2` seul deux candidats seront proposés, `1` et `2`. Il peut être utile de ne pas
230 les dédoublonner, en particulier en combinaison avec l'option précédente `-d`.
231 On peut par exemple vouloir proposer le retrait d'un élément qui apparaît à
232 plusieurs endroits dans une base de donnée sous plusieurs formes différentes. Il
233 faut donc que le candidat puisse apparaître plusieurs fois pour être associé
234 correctement au tableau du menu de choix. Pour ne pas dédoublonner il faut
235 utiliser l'option `-2` :
236
237 ```
238 desc="(
239 dépense1\ blabla\ truc
240 dépense1\ bidule\ machin
241 dépense2\ chouette\ aaaa
242 )"
243 compadd -J a -2 -ld $desc 1 1 2
244 ```
245
246 A noter que, comme l'option `-o`, cette option nécessite l'option `-J`. Cette
247 option est utilisée lors du retrait d'une dépense, vers la seconde 52 de la
248 vidéo de résultat. On y voit trois options dans le menu dont les deux premières
249 sont associée à deux candidats de valeurs `1`. Avec dédoublonnage cela n'aurait
250 pas été possible.
251
252 ### Les variables d'environnements
253
254 #### Savoir à quel numéro d'argument on en est avec `$CURRENT`
255
256 Dans la variable `$CURRENT` se trouve le numéro du mot que l'on est en train
257 d'écrire/auto-compléter. Le décompte commence à 1 et le premier mot est toujours
258 la commande en cours. Le premier paramètre (argument ou option, peu importe) est
259 donc à 2 et ainsi de suite. En utilisant `compadd -x` pour visualiser la valeur
260 de la variable en dessous de la commande :
261
262 <video src="current-auto.mp4" controls loop loading=lazy>
263
264 On peut utiliser le contenu de cette variable pour faire
265 varier l'auto-complétion, voir l'exemple ci-dessous.
266
267 #### Connaître la valeur d'un mot déjà rempli avec `$words`
268
269 Il peut être utile de savoir quelle est la valeur d'un paramètre déjà écrit.
270 Pour cela on peut lire dans le tableau `$words` à l'indice correspondant. Le
271 premier éléments (`$words[1]`) est toujours le nom de la commande en cours, le
272 second (`words[2]`) le premier paramètre etc. En utilisant la même astuce que
273 précédemment :
274
275 <video src="words-auto.mp4" controls loop loading=lazy>
276
277 ### Tout mettre ensemble, l'exemple de tricount
278
279 Voyons comment utiliser tout ça pour reconstruire l'auto-complétion de
280 `tricount`. Je commente le code ligne par ligne en passant vite sur les aspects
281 purement shell.
282
283 D'abord, déclarer la fonction au nom `_commande` et inscrire quelle commande
284 elle auto-complète :
285
286 ```
287 #compdef tricount
288 _tricount() {
289 ```
290
291 Ensuite écrire éventuellement en dur l'endroit où se trouve les bases de données
292 et récupérer la valeur de la base courante, de l'action à mener dessus et
293 l'objet :
294
295 ```
296 local BDDFOLDER="/srv/tricount"
297 local curbdd="$words[2]"
298 local action="$words[3]"
299 local objet="$words[4]"
300 ```
301
302 Puisque cette fonction est appelée à chaque fois que la touche tabulation est
303 lancée les variables `curbdd`, `action` et `objet` peuvent très bien être vides
304 parce que la liste `$words` n'est pas encore remplie.
305
306 Si on est au deuxième argument c'est que l'on cherche à choisir une base de
307 donnée. Il faut récupérer la liste en regardant dans le dossier correspondant.
308 S'il y en a au moins une on les ajoute en tant que candidats avec un message
309 explicatif. S'il n'y en a pas on peut pré-remplir la commande pour en créer une
310 avec un nom bidon modifiable :
311
312 ```
313 if [ "$CURRENT" = 2 ];then
314 bdds=$(find $BDDFOLDER -type f | cut -d'/' -f4 | sort)
315 if [ "$bdds" ];then
316 compadd -X "Choisir une base de donnée" $bdds
317 else
318 compadd -Qx "Aucune bdd de dispo, go en créer une" "nom-bdd creer"
319 fi
320 fi
321 ```
322
323 Si on est au troisième argument c'est que l'on cherche à effectuer une commande
324 sur une bdd existante ou pas. Si la bdd n'existe pas on ajoute techniquement
325 l'action `creer` en tant que candidat. Sinon on prépare les variables contenant
326 les candidats et leurs descriptions en faisant usage de `-l` et `-d`.
327
328 ```
329 if [ "$CURRENT" = 3 ];then
330 if ! [ -f $BDDFOLDER/$curbdd ];then
331 compadd creer
332 else
333 actions=(ajouter retirer lister calculer)
334 desc="(
335 ajouter\ \ --\ Ajouter\ une\ dépense\ ou\ une\ personne
336 retirer\ \ --\ Retirer\ une\ dépense\ ou\ une\ personne
337 lister\ \ \ --\ Afficher\ le\ contenu\ de\ la\ bdd
338 calculer\ --\ Calculer\ qui\ doit\ combien\ à\ qui
339 )"
340 compadd -X "Choisir une action" -J a -o nosort -ld $desc $actions
341 fi
342 fi
343 ```
344
345 Si on est au quatrième argument et que l'action (le troisième) est `ajouter` ou
346 `retirer` alors on propose un objet à ajouter ou retirer :
347
348 ```
349 if [ "$CURRENT" = 4 ] && { [ "$action" == "ajouter" ] || [ "$action" == "retirer" ]; };then
350 compadd -X "Choisir un objet à $action" depense personne
351 fi
352 ```
353
354 Si l'action est `retirer` et l'objet `depense` alors on récupère les
355 identifiants des dépenses et on construit ensuite un tableau pour l'affichage du
356 menu en réorganisant les lignes de dépenses de la bdd et en échappant les
357 espaces[^7]. Finalement on ajoute les identifiants en tant que candidats et les
358 lignes de dépenses en tant qu'option visuelles. Aussi on retire le tri par
359 défaut qui mélangerait toutes les dépenses et on demande à ne pas supprimer les
360 candidats doublons. Ainsi les éventuelles multiples lignes pour une dépense
361 donnée auront bien l'identifiant de la dépense en candidat en face.
362
363 ```
364 if [ "$action" = "retirer" ] && [ "$objet" = "depense" ];then
365 ids=($(< "$BDDFOLDER/$curbdd" cut -f5 | sed 1d | paste -s -d' '))
366 # Ex: ids="1 1 2"
367 desc="(
368 $(< "$BDDFOLDER/$curbdd" awk 'BEGIN{OFS="\t"};NR>1{print $5,$1,$2,$3,$4}' | column -ts' ' | sed 's# #\\ #g')
369 )"
370 # Ex: desc="(
371 # dépense1\ blabla\ truc
372 # dépense1\ bidule\ machin
373 # dépense2\ chouette\ aaaa
374 # )"
375 compadd -X "Choisir une dépense à retirer" -J a -2 -o nosort -ld $desc $ids
376 fi
377 ```
378
379 Si l'action est `retirer` et l'objet de retrait une `personne` alors on récupère
380 la liste des personnes dans la base de donnée. Si la liste est vide on affiche
381 un message d'erreur comme quoi il n'y a personne à retirer, sinon on ajoute la
382 liste en candidats :
383
384 ```
385 if [ "$action" = "retirer" ] && [ "$objet" = "personne" ];then
386 personnes=($(< "$BDDFOLDER/$curbdd" head -n1 | tr ' ' '\n' | sed 1d | sort))
387 if ! [ "$personnes" ];then
388 compadd -x "Il n'y a aucune personne à retirer"
389 else
390 compadd -X "Choisir une personne à retirer" -o nosort $personnes
391 fi
392 fi
393 ```
394
395 Si l'action est `ajouter` et l'objet une `depense` alors on récupère la liste
396 des personnes de la base de donnée :
397
398 ```
399 if [ "$action" = "retirer" ] && [ "$objet" = "personne" ];then
400 personnes=($(< "$BDDFOLDER/$curbdd" head -n1 | tr ' ' '\n' | sed 1d | sort))
401 ```
402
403 Puis on vérifie à quelle étape de la construction de la dépense on
404 est. Si l'on est au paramètre 5 c'est le début et on cherche à ajouter la
405 personne qui paye. S'il n'y a pas de candidats disponible on peut afficher un
406 message d'erreur :
407
408 ```
409 if [ "$CURRENT" = 5 ];then
410 if ! [ "$personnes" ];then
411 compadd -x "Pas de personnes disponibles :("
412 compadd -x "Vous pouvez tout de même entrer un nom, ça fonctionnera"
413 else
414 compadd -X "Choisir la personne qui paye" $personnes
415 fi
416 fi
417 ```
418
419 Si l'on est à l'argument 6 on cherche à ajouter un montant :
420
421 ```
422 [ "$CURRENT" = 6 ] && compadd -X "Choisir un montant" -J a -o nosort $(seq 1 50)
423 ```
424
425 Si l'on est à l'argument 7 on cherche à ajouter une raison pour la dépense. Il
426 est possible de faire un peu de pré-traitement sur les candidats pour qu'ils
427 évoluent avec la base de donnée. Ici les raisons apparaîtront dans l'ordre de la
428 plus utilisée à la moins utilisée avec quelques raisons d'exemple en bonus à la
429 fin :
430
431 ```
432 if [ "$CURRENT" = 7 ];then
433 raisons=($(< "$BDDFOLDER/$curbdd" cut -f4 | sed 1d | sort | uniq -c | awk '{print $2}' | paste -s -d' '))
434 compadd -X "Mettre une raison" -J a -o nosort $raisons repas transport courses ...
435 fi
436 ```
437
438 Puis finalement si l'on est à l'argument 8 on chercher à ajouter les
439 bénéficiaires de la dépense. On peut afficher plusieurs lignes de messages en
440 multipliant les appels à `compadd -x`. On peut ajouter "à la main" un candidat
441 en plus de ceux récoltés dans une liste comme le candidat `toustes` ici :
442
443 ```
444 if [ "$CURRENT" -ge 8 ];then
445 if ! [ "$personnes" ];then
446 compadd -x "Pas de personnes disponibles :("
447 compadd -x "Vous pouvez tout de même entrer un nom, ça fonctionnera"
448 else
449 compadd -X "Choisir une ou plusieurs personnes bénéficiaires" $personnes toustes
450 fi
451 fi
452 ```
453
454 Cet exemple n'est pas parfait. On pourrait factoriser un certain nombre de
455 choses et sortir de la fonction rapidement après avoir ajouté des candidats
456 plutôt que de faire tous les tests alors même que l'on sait qu'ils seront faux.
457 Il est ici à titre d'exemple.
458
459 ## Installation
460
461 Pour activer l'auto-complétion `zsh` dans toutes ces sessions il faut ajouter
462 les lignes suivantes dans son fichier `~/.zshrc`[^3] :
463
464 ```
465 autoload -Uz compinit
466 compinit
467 # Pour pouvoir parcourir le menu des suggestions
468 # avec les flèches comme dans les vidéos
469 zstyle ':completion:*' menu yes select
470 ```
471
472 Il faut ensuite écrire la fonction d'auto-complétion avec ceci pour toute
473 première ligne :
474
475 ```
476 #compdef cmd
477 _cmd() {
478 [...]
479 }
480 ```
481
482 Cette première ligne est un "faux" commentaire permettant à `zsh` de savoir que
483 la fonction qui suit doit être utilisée pour compléter la commande `cmd` comme
484 si l'on avait lancé `compdef _cmd cmd` à la main.
485
486 Finalement il faut installer le fichier, préférablement nommé `_cmd` dans le
487 dossier `/usr/share/zsh/functions/Completion/Unix/_cmd`[^8]. Au lancement `zsh`
488 lit tous les fichiers présents dans ces dossiers, regarde la première ligne et
489 fait l'association entre la fonction de complétion et la commande.
490
491 ## De l'auto-complétion personnalisée ?
492
493 L'un des mécanismes principaux pour faciliter la découvrabilité et l'usage du
494 shell, notamment des commandes les plus complexes, est de restreindre l'espace
495 d'exploration. C'est ce qui est par exemple fait dans [cet
496 article](https://dl.acm.org/doi/10.1145/3332165.3347944)[^12] via un système capable
497 de parser un ensemble restreint de commandes shell, sélectionné par un·e
498 experte, et rendant une GUI exposant les options et arguments utilisé.es
499 par ce sous-ensemble plutôt que la totalité des fonctionnalités de la commande.
500
501 C'est également en partie l'idée derrière
502 [`zenu`](http://arthur.bebou.netlib.re/zenu), à savoir mettre des commandes
503 parfois complexes derrière des menus pour faciliter la navigation, l'usage et le
504 partage de ces commandes tout en diminuant la charge cognitive.
505
506 Malheureusement les fonctions d'auto-complétion fournies par défaut avec `zsh`
507 laissent à désirer de côté là. Par exemple lorsque l'on auto-complète la
508 commande `convert` d'image-magick après avoir écrit un `-` dans `zsh` on obtient
509 :
510
511 
514
515 C'est sympa d'avoir des petites descriptions mais la taille de la liste est
516 intimidante et rend la complétion assez peu utile. Ce n'est pas un diss contre
517 les contributeurices des fonctions de complétion de `zsh`, cela s'explique par
518 le fait que :
519
520 1. `zsh` est utilisé par des (dizaines de ?) millions de personne dans le
521 monde. Il n'est donc pas possible de créer une fonction de complétion qui
522 convienne à tout le monde. À défaut la philosophie retenue semble être de
523 faire une fonction assez peu directive mais exhaustive.
524 2. Image-magick comporte un nombre incalculable de fonctionnalités (peut-être
525 trop).
526
527 J'émets l'hypothèse qu'en adoptant une approche située, en sachant pour *qui* et
528 *quels usages* on créé *les* fonctions de complétion, il serait possible d'en
529 faire des outils pédagogiques intéressants. Il n'y aurait pas *une* fonction
530 d'auto-complétion exhaustive mais ne satisfaisant réellement personnes mais une
531 multitude de fonctions que l'on se partagerait selon nos pratiques ou notre
532 niveau de familiarité avec l'outil.
533
534 Bien sûr cela nécessite d'écrire du code mais c'est pour ça que je fais ce tuto
535 :)
536
537 ## Références
538
539 La doc `zsh` de référence à propos de `compadd` est ici :
540 https://zsh.sourceforge.io/Doc/Release/Completion-Widgets.html#Completion-Builtin-Commands
541
542 [^1]: `yt-dlp -h | wc -l` = 892. Et en plus faut attendre deux secondes pour que ça s'affiche.
543 [^2]: Par moderne j'entends sous la forme que l'on utilise aujourd'hui depuis [au moins la version de `zsh` datant de 1999](https://github.com/zsh-users/zsh/commit/e74702b467171dbdafb56dfe354794a212e020d9#diff-ce02ccc8e9de1903cddd3276d6b5b986c204822c6c6d7d4b22f6db73d77ea816R1) et [depuis bien plus longtemps de manière plus primitive dans d'autres shells](https://developer.ibm.com/tutorials/l-linux-shells/).
544 [^3]: Ou tout autre endroit qui est sourcé à la création de chaque shell
545 interactif, si vous sachez vous sachez
546 [^4]: aussi connue sous le nom de la touche "flèche flèche"
547 [^5]: en `zsh` pas besoin du `;` de fin quand on écrit des fonctions sur une
548 seule ligne mais en, team posix ici
549 [^6]: la documentation `zsh` précise que `compadd` est assez "bas niveau" et
550 qu'il est souvent préférable d'utiliser les très nombreuses autres fonctions
551 proposées par `zsh` wrappant `compadd`. Le souci est qu'elles sont très
552 nombreuses, compliquées et qu'elles sont surtout utiles pour faire de
553 l'auto-complétion de commandes respectant des conventions bien établies
554 (combo d'option courtes et longues `-` `--`, certaines des flags, d'autres
555 suivies d'une chaÎne de caractère, parfois des fichiers, parfois des IP
556 etc). Puisque l'on fait un peu n'imp avec `tricount` et que la documentation
557 est assez opaque j'ai trouvé qu'il était plus facile d'apprendre uniquement
558 `compadd` en partant du principe que tout était possible avec.
559 [^7]: Un peu de quoting hell ici puisque je connais très mal zsh et ses
560 structures de données. Je pense qu'on peut faire mieux
561 [^8]: du moins pour Debian, probablement pour tous les linux.
562 [^9]: J'utilise "auto-complétion" et "complétion" de manière interchangeable
563 [^10]: Ou carrément exécuter des commandes pour lancer un logiciel ou je ne sais
564 trop quoi d'autre. C'est étrange parce que ce n'est clairement pas ce qui
565 est attendu par les utilisateurices mais peut-être que ça peut convenir à
566 votre manière de travailler.
567 [^12]: A propos duquel je pense écrire un article de blog bientôt d'ailleurs