Écrire une autocomplétion par tabulation simple dans Bash et Zsh
(mill-build.org)- Présentation d’une méthode pour implémenter une fonctionnalité d’autocomplétion par tabulation avec affichage de descriptions, y compris pour des mots déjà complétés, dans Bash et Zsh
- Bash et Zsh utilisent des API d’autocomplétion différentes, et seul Zsh fournit nativement l’affichage des descriptions dans l’autocomplétion
- La structure consiste à générer les candidats avec
_generate_foo_completions, puis à les renvoyer viaCOMPREPLYdans Bash etcompadddans Zsh - Pour reproduire dans Bash la fonctionnalité de description de Zsh, on inclut la description dans la chaîne candidate, puis on la supprime uniquement lorsqu’il n’y a qu’un seul candidat
- Même en présence d’un seul candidat, on améliore le comportement en ajoutant volontairement une ambiguïté afin d’afficher la description lors de l’appui sur
<TAB> - Le script final offre la même expérience utilisateur dans les deux shells et prend en charge la complétion partielle, la complétion totale et l’affichage des descriptions des candidats
Contexte du problème
- L’autocomplétion par tabulation (tab-completion) est utile pour explorer des commandes ou des flags, en particulier lorsqu’on découvre une API ou un outil CLI
- Par défaut, Zsh n’affiche les descriptions que lorsqu’il y a plusieurs candidats, et Bash ne le permet qu’au prix d’une configuration supplémentaire
- Mais pour un mot déjà entièrement complété, aucun des deux shells n’affiche de description
- L’utilisateur doit donc passer par une procédure fastidieuse pour voir la description :
- supprimer quelques caractères pour faire correspondre plusieurs candidats
- appuyer sur la touche
<TAB>pour afficher la liste des candidats - repérer visuellement la description voulue
- retaper les caractères supprimés pour exécuter la commande
Aperçu de la solution
- Même lorsqu’il n’y a qu’un seul candidat, on ajoute un candidat factice (dummy completion) pour créer une ambiguïté
- Cela permet à Bash comme à Zsh d’afficher la liste des candidats avec leurs descriptions
- Il faut toutefois veiller à ce que le texte de description ne soit pas inséré dans la commande réelle
Concepts de base
- Lorsqu’on appuie sur
<TAB>, l’autocomplétion reçoit le mot courant et la position du curseur, puis renvoie une liste de candidats possibles - Bash : affectation des candidats dans le tableau
COMPREPLY - Zsh : enregistrement des candidats via la commande
compadd - La fonction
_generate_foo_completionsaffiche les chaînes candidates et peut, en pratique, les générer dynamiquement selon l’état du CLI
Prise en charge simultanée de Bash et Zsh
- Implémentation adaptée à chaque shell avec les fonctions
_complete_foo_bashet_complete_foo_zsh - Distinction via
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi - L’utilisateur enregistre ensuite le script dans
.bashrcou.zshrcavant de l’appliquer
Affichage des descriptions dans Zsh
- Les chaînes candidates utilisent le format
nom: description - Zsh : transmission parallèle du nom et de la description via
compadd -d raw -- $trimmed - Bash : seuls les candidats sans la partie description sont transmis à
COMPREPLY(pas de prise en charge native des descriptions)
Implémenter les descriptions dans Bash
- En cas de candidats multiples, on affiche directement les chaînes contenant les descriptions
- En cas de candidat unique, on supprime seulement la description
- On exploite le comportement de Bash, qui n’insère que le préfixe commun lors de l’autocomplétion, afin d’éviter que la description ne soit ajoutée à la saisie réelle
Afficher une description même avec un seul candidat
- Pour montrer la description même lorsqu’un mot est déjà complété et que l’utilisateur appuie sur
<TAB>, on ajoute un candidat factice pour provoquer une ambiguïté - Zsh : ajout du candidat factice dans les deux tableaux parallèles (
raw,trimmed) - Bash : lorsqu’il n’y a qu’un seul candidat, ajout du nom seul dans
trimmed
Résultat final
- En cas de candidats multiples, le nom et la description sont tous deux affichés
- Même avec un candidat unique, il est possible de consulter la description via
<TAB> - Bash et Zsh offrent tous deux une expérience identique
- Exemple d’utilisation :
$ foo <TAB> apple: a common fruit banana: starchy and high in potassium apricot: sour fruit... cherry: small and sweet...
1 commentaires
Avis Hacker News
fish_update_completions~/.cache/fish/generated_completions/curlavec-L→ 'Follow redirects',-O→ 'Write output to file named as remote file'car TABse développe enblkdiscard, ce qui provoque des dysfonctionnements même si cargo n’est pas dans le PATH--help, je me demande si fish a un équivalent de_gnu_genericde zsh ou decomplete -F _longoptde bashzypper search fish-completion, plus de 200 paquets sont sortis, ce qui m’a paru un peu louchecomplete-filename, liée à M-/, qui complètent uniquement des noms de fichiers sans tenir compte du contextels, puis en remplaçant la commandecomplete -r, tout fonctionne comme souhaité laisse penser que le problème vient des scripts bash-completion$fpathpour qu’il soit mis en cache, ce qui accélère le temps de démarrage_gnu_genericpermet une complétion simple basée sur--help--generatede ripgrep, ou la génération de complétion à l’exécution dans PHP Symfony--completionque les bibliothèques de parsing communes implémenteraient automatiquementcomplete_kill_1, on obtient la complétion du premier argument de la commandekillset-java-home, j’utilise_describepour compléter les versions à partir de la liste~/apps/java/*