Ajouter l'auto‑complétion à vos scripts Bash et zsh

La complétion par tabulation rend vos scripts plus faciles à utiliser et à découvrir. Ce guide explique comment ajouter une auto‑complétion simple pour zsh et Bash, présente une version portable qui détecte le shell et fournit des conseils de test, des modèles et une checklist pour la mise en production.
L’auto‑complétion accélère l’utilisation des outils en réduisant la frappe et en rendant les commandes auto‑documentées. Les shells modernes comme zsh et bash fournissent des mécanismes pour enrichir l’expérience de l’utilisateur avec des suggestions pour des commandes, des noms de fichiers, des options et des sous‑commandes.
Important: la complétion s’exécute dans le shell de l’utilisateur, pas dans le binaire de votre programme. Vous fournissez des règles que le shell utilise quand l’utilisateur presse Tab.
Comment fonctionne la complétion par Tab
L’auto‑complétion existe dans Unix depuis les années 80. Les shells examinent le contexte (ce qui a été tapé, où se trouve le curseur) pour proposer des complétions pertinentes.
- La complétion de commandes parcourt le PATH pour trouver les exécutables commençant par les lettres tapées.
- La complétion de chemins propose des fichiers et dossiers (relatifs ou absolus) et résout les ambiguïtés.
- La complétion d’arguments s’applique à tout ce qui suit le nom de la commande: options, sous‑commandes, identifiants, etc.
Définition: auto‑complétion – mécanisme qui propose des termes (commandes, fichiers, options) en fonction du texte déjà saisi.
Exemple pratique: un script « todos » simple
Nous allons montrer la complétion d’arguments pour un script minimaliste qui gère une liste de tâches. Le comportement importe peu; le but est d’illustrer la manière d’ajouter des suggestions.
Code du script (zsh/bourne compatible) :
#!/usr/bin/env zsh
FILE="$HOME/.local/state/todos/data"
if [ "$#" -eq "1" ] && [ "$1" = "edit" ] ; then
"${EDITOR:-vi}" "$FILE"
elif [ "$#" -eq "1" ] && [ "$1" = "help" ] ; then
echo "Usage: $(basename $0) [ edit | help ]"
else
<"$FILE" grep -v ^~
fi
Commandes disponibles après installation du script dans le PATH et rendu exécutable:
- todos : affiche le contenu du fichier data en ignorant les lignes commençant par ~
- todos help : affiche l’aide
- todos edit : ouvre le fichier dans l’éditeur
Vous pouvez créer un script vide et rendre exécutable pour tester la logique de complétion sans implémenter toute la logique métier.
Ajouter une complétion simple pour zsh
Pour zsh, la complétion la plus basique est très simple : définissez une fonction qui appelle compadd avec la liste des suggestions, chargez compinit, puis liez la fonction à la commande.
_complete_todos() {
compadd help edit
}
autoload -Uz compinit
compinit
compdef _complete_todos todos
Explication rapide:
- compadd : ajoute des mots proposés à zsh.
- compinit : initialise le système de complétion de zsh.
- compdef : associe votre fonction à la commande.
Où placer ce code :
- Dans ~/.zshrc (pour développement rapide).
- Dans un fichier sous un répertoire référencé par $fpath, dont le nom commence par un underscore (_todos) pour que zsh puisse l’autoloader.
Note: zsh propose aussi des helpers avancés comme _arguments et _files pour gérer options et chemins.
Comportement et différences dans Bash
Bash adopte une approche moins magique : il vous laisse décider quelles suggestions sont pertinentes. L’équivalent naïf est :
_complete_todos_bash() {
COMPREPLY=(help edit)
}
complete -F _complete_todos_bash todos
Explication :
- complete : enregistre une fonction de complétion pour la commande.
- COMPREPLY : variable tableau que la fonction doit remplir avec les propositions.
Problème courant : bash ne filtre pas automatiquement les propositions en fonction de ce qui est tapé. Par exemple :
$ todos he
help edit
Ici, il faut dire à bash de ne proposer que « help » quand l’utilisateur a tapé “he”. Pour cela, bash fournit des variables utiles :
- COMP_WORDS : tableau des mots de la ligne de commande actuelle.
- COMP_CWORD : index du mot en cours de complétion.
Et une commande d’aide, compgen, qui peut générer des suggestions filtrées :
$ compgen -W "one two three" o
one
$ compgen -W "one two three" t
two
three
Ainsi, on peut écrire :
_complete_todos_bash() {
COMPREPLY=( $( compgen -W "edit help" -- "${COMP_WORDS[$COMP_CWORD]}" ) )
}
complete -F _complete_todos_bash todos
Variantes utiles en bash :
- compgen -f : proposer des noms de fichiers.
- compgen -d : proposer des répertoires.
- compopt -o nospace : empêcher l’ajout d’un espace automatique après la complétion (utile pour options qui attendent un =).
Important: vérifiez la compatibilité avec la version de bash cible si vous utilisez compopt, car certaines options sont spécifiques à bash-completion.
Version portable pour zsh et Bash
Voici un exemple complet qui détecte le shell et applique la logique adaptée :
SUBCOMMANDS=(help edit halt)
_complete_todos_zsh() {
compadd $SUBCOMMANDS
}
_complete_todos_bash() {
COMPREPLY=( $( compgen -W "${SUBCOMMANDS[*]}" -- "${COMP_WORDS[$COMP_CWORD]}" ) )
}
if [ -n "${ZSH_VERSION:-}" ]; then
autoload -Uz compinit
compinit
compdef _complete_todos_zsh todos
elif [ -n "${BASH_VERSION:-}" ]; then
complete -F _complete_todos_bash todos
fi
Conseils de déploiement :
- Stockez ce script dans un fichier (par exemple completion.sh) et sourcez‑le depuis ~/.bashrc ou ~/.zshrc :
. /path/to/completion.sh
- Pour partager une complétion avec les utilisateurs d’un paquet, placez le fichier pour bash dans /etc/bash_completion.d/ et le fichier zsh dans un dossier fpath approprié, ou fournissez des instructions pour l’ajout au dotfile.
Scénarios plus avancés et limites (quand ça échoue)
Counterexamples / quand cela échoue :
- Comportement multi‑mot : si la complétion dépend d’autres arguments déjà fournis, un simple compadd/COMPREPLY statique ne suffit.
- Sous‑commandes dynamiques : si la liste de sous‑commandes provient d’un serveur ou d’une configuration modifiable, il faut générer la liste à la volée.
- Conflits de complétion : plusieurs fichiers de complétion peuvent entrer en conflit. Le shell charge souvent la dernière définition.
- Différences de versions : les helpers (compopt, certaines options de compgen) varient selon la version de bash/bash‑completion.
Exemples d’échecs concrets :
- Vous proposez des fichiers mais oubliez d’utiliser compgen -f; bash proposera des mots non valides.
- Vous fournissez « help edit » mais oubliez d’exclure la sous‑commande « help » lorsque d’autres drapeaux demandent un fichier.
Approches alternatives
- argcomplete (Python) : pour les scripts Python, argcomplete peut générer la complétion à partir d’argparse.
- Click (Python) : framework CLI qui peut générer des complétions shell automatiquement.
- Cobra (Go) : framework pour CLI qui intègre la génération de scripts de complétion.
- Utiliser des utilitaires existants : many GNU utilities et outils modernes fournissent déjà des scripts de complétion prêts à l’emploi.
Ces solutions conviennent si vous développez une application distribuée ou un véritable CLI à options complexes.
Mental models et heuristiques
- Principe KISS : commencez par une liste statique de sous‑commandes, puis complexifiez au besoin.
- Local first : si la liste vient d’un fichier local, lisez‑la; si elle dépend d’un réseau, mettez en cache pour ne pas bloquer la complétion.
- Explicitez le contexte : utilisez COMP_WORDS/COMP_CWORD (bash) ou les helpers zsh (_arguments) pour connaître le mot en cours.
Fiche pratique (fact box)
- Langages visés : shell (bash, zsh)
- Outils utiles : compadd (zsh), compinit (zsh), compdef (zsh), compgen (bash), complete (bash), COMPREPLY (bash)
- Déploiement courant : ~/.bashrc, ~/.zshrc, /etc/bash_completion.d/, $fpath pour zsh
- Risques : conflits de fichiers de complétion, dépendances à la version du shell
Mini‑méthodologie pour développer une complétion fiable
- Commencez par un prototype statique (compadd / COMPREPLY avec compgen).
- Testez localement en sourçant votre fichier et en essayant plusieurs scénarios.
- Traitez les cas contextuels (ex : argument dépend d’un flag précédent).
- Ajoutez mise en cache si vous interrogez des sources lentes.
- Documentez l’emplacement et la façon d’activer la complétion pour l’utilisateur.
- Intégrez des tests automatisés (voir checklist QA ci‑dessous).
Checklist par rôle
Développeur
- Fournir un script de complétion minimal.
- Documenter comment sourcer le script.
- Prévoir une génération dynamique si nécessaire.
Mainteneur de paquet
- Installer le script dans /etc/bash_completion.d/ (bash).
- Placer un fichier fpath/_nom pour zsh ou documenter l’installation.
- Tester l’absence de conflit avec d’autres scripts.
QA / Testeur
- Vérifier complétions pour mot vide, préfixes partiels, et mots composés.
- Tester sous bash (au moins 4.x) et zsh (versions courantes).
- Tester cas d’erreur et latence (complétion asynchrone ou cache si nécessaire).
Tests et critères d’acceptation
Cas de test essentiels :
- TC1 : « todos
» propose la liste complète de sous‑commandes. - TC2 : « todos he
» ne propose que « help ». - TC3 : « todos ed
» ne propose que « edit ». - TC4 : quand le script fournit des chemins, la complétion montre uniquement des fichiers existants.
- TC5 : pas d’erreurs visibles dans le shell lors de l’appui sur Tab.
Critères d’acceptation : la complétion propose un ensemble raisonnable d’options pertinentes pour chaque contexte sans provoquer d’erreurs visibles ni ralentir notablement l’utilisation du shell.
Modèles et snippets utiles
Snippet pour compléter des fichiers en bash :
# dans la fonction de complétion bash
local cur
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $( compgen -f -- "$cur" ) )
Snippet pour empêcher l’ajout d’espace après complétion (bash) :
# empêche l'ajout d'un espace automatique
compopt -o nospace
Snippet zsh utilisant _arguments (exemple simple) :
# fichier _todos pour fpath
#compdef todos
_arguments \
'1: :->subcmd' \
'*: :->args'
case $state in
subcmd)
_values 'sous-commande' edit help halt
;;
esac
Compatibilité et migration
- Si vous ciblez plusieurs distributions, testez avec bash 4.x et zsh 5.x au minimum.
- Pour les scripts partagés dans une équipe hétérogène, fournissez un fichier d’installation simple et documenté.
- Pour les projets open source, ajoutez la génération des scripts de complétion dans votre pipeline CI si votre CLI est généré (ex : Cobra/Click).
Glossaire (une ligne)
- compadd : fonction zsh pour ajouter des complétions.
- compinit : initialise le système de complétion de zsh.
- compdef : associe une fonction de complétion à une commande en zsh.
- compgen : utilitaire bash pour générer des propositions.
- COMPREPLY : tableau bash attendu par complete.
- complete : commande bash pour enregistrer une fonction de complétion.
Résumé
La complétion par Tab améliore l’ergonomie de vos scripts. Commencez simple avec des listes statiques, puis enrichissez la logique pour gérer des sous‑commandes dynamiques ou des arguments contextuels. Testez sous les shells ciblés et documentez l’installation pour vos utilisateurs.
Notes:
- Si vous développez en Python ou Go, considérez argcomplete, Click ou Cobra pour générer automatiquement des scripts de complétion.
- Évitez d’effectuer des appels réseau bloquants pendant la complétion ; utilisez le cache ou une génération asynchrone si nécessaire.
Matériaux similaires

Empêcher les applications Android en arrière-plan
Redimensionner un RAID dégradé (/dev/md1)

Réparer le son des Stories Instagram sur iPhone

Traquer et se protéger des numéros frauduleux

Auto‑complétion pour scripts Bash et zsh
