Veuillez m'excuser si je fais quelque chose de stupide ici, la documentation est énorme et la recherche n'a encore rien donné.
J'essaie de créer des complétions shell pour mon script personnalisé appelé fab
. Pour bash, c'était facile, il suffit de les déposer dans /etc/bash_completion.d
et ils fonctionnent. Mais oh boy, est-ce que zsh est un PITA…
J'ai la fonction de complétion _fab
et cela fonctionne bien lorsqu'il est activé avec compdef _fab fab
. Je l'ai mis dans /usr/share/zsh/vendor-completions/_fab
qui était déjà dans mon $fpath
. Le fichier commence par #compdef fab
et se termine par compdef _fab fab
. Ça a l'air bien :
$ type _fab
_fab is an autoload shell function
Mais chaque fois que je démarrais un nouveau shell, fab
les complétions ne fonctionnaient pas (autres fonctions de vendor-completions
, comme _docker
, nous allons bien). compinit
corrigé cela pour ce shell spécifique. J'ai compris que rm ~/.zcompdump ~/.zcompdump-$(hostname)-5.1.1; compinit
faites-le fonctionner en permanence (5.1.1 =ma version zsh).
Questions :
- Quand et quoi lit
~/.zcompdump
configurer les complétions initiales ? -
man zshall
dit :La prochaine invocation de compinit lira le fichier vidé au lieu d'effectuer une initialisation complète.
Si tel était le cas,
compinit
ne corrigeait pas mes complétions avant de supprimer~/.zcompdump
, à droite? Ai-je raté quelque chose ? - Qu'est-ce que
~/.zcompdump-$(hostname)-5.1.1
et comment est-il lié à.zcompdump
? La seule différence est une complétion qui se trouve dans~/.oh-my-zsh/completions
(parce que$ZSH
pointe vers~/.oh-my-zsh
). Est-ce un truc oh-my-zsh ? - Si je devais regrouper ces complétions dans un package redistribuable ou créer un script d'installation, où dois-je placer les complétions zsh et que dois-je faire d'autre pendant l'installation pour m'assurer que tout fonctionne correctement ?
Je cible Ubuntu 16.04, 18.04 et 19.04, mais les informations non spécifiques à la distribution sont les bienvenues. Je teste cela sur Ubuntu 16.04 avec zsh 5.1.1 et le récent oh-my-zsh.
Réponse acceptée :
TL,DR :Dans les opérations normales, déposez simplement le fichier dans le répertoire approprié. Pendant le test, vous devez supprimer le fichier cache (.zcompdump
par défaut, mais les utilisateurs peuvent le placer dans un emplacement différent, et oh-my-zsh le place dans un emplacement différent).
La réponse simple est d'écrire la fonction de complétion dans un fichier où la première ligne est #compdef fab
. Le fichier doit être dans un répertoire sur $fpath
.
Le fichier peut soit contenir le corps de la fonction, soit une définition de la fonction suivie d'un appel à la fonction. Autrement dit, soit le fichier contient quelque chose comme
#compdef fab
_arguments …
ou
#compdef fab
function _fab {
_arguments …
}
_fab "[email protected]"
Le fichier doit être présent sur $fpath
avant compinit
court. Cela signifie que vous devez faire attention à l'ordre des choses dans .zshrc
:ajoutez d'abord tous les répertoires personnalisés à $fpath
, puis appelez compinit
. Si vous utilisez un framework tel que oh-my-zsh, assurez-vous d'ajouter tous les répertoires personnalisés à $fpath
avant le code oh-my-zsh.
compinit
est la fonction qui initialise le système de complétion. Il lit tous les fichiers dans $fpath
et vérifie leur première ligne pour les directives magiques #autoload
et #compdef
.
.zcompdump
est un fichier cache utilisé par compinit
. ~/.zcompdump
est l'emplacement par défaut ; vous pouvez choisir un emplacement différent lors de l'exécution de compinit
. Oh-my-zsh appelle compinit
avec le -d
option pour utiliser un nom de fichier de cache différent donné par la variable ZSH_COMPDUMP
, qui par défaut est
ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
Le nom d'hôte est inclus pour le bien des personnes dont le répertoire personnel est partagé entre les machines et qui peuvent avoir différents logiciels installés sur différentes machines. La version zsh est incluse car le fichier cache est incompatible entre les versions (il inclut du code qui change d'une version à l'autre).
Connexe :Que fait CTRL+V dans vim ?
Je pense que tous vos problèmes sont dus à un fichier de cache obsolète (et cela vous a compliqué la situation). Malheureusement, l'algorithme de zsh pour déterminer si le fichier cache est obsolète n'est pas parfait, probablement dans l'intérêt de la vitesse. Il ne vérifie pas le contenu ou les horodatages des fichiers sur $fpath
, il ne fait que les compter. Un .zcompdump
le fichier commence par une ligne comme
#files: 858 version: 5.1.1
Si la version de zsh et le nombre de fichiers sont corrects, zsh charge le fichier cache.
Le fichier cache ne contient que des associations entre les noms de commande, pas le code des fonctions de complétion. Voici quelques scénarios courants dans lesquels le cache fonctionne de manière transparente :
- Si vous ajoutez un nouveau fichier à
$fpath
, cela invalide le cache. - Plus généralement, si vous ajoutez et supprimez des fichiers sur
$fpath
, et que le nombre total de fichiers supprimés n'est pas le même que le nombre total de fichiers supprimés, cela invalide le cache. - Si vous déplacez un fichier vers un autre répertoire dans
$fpath
sans changer son nom, cela n'affecte rien de ce qui se trouve dans le cache, donc le cache reste correct. - Si vous modifiez un fichier dans
$fpath
sans changer sa première ligne, cela n'affecte rien de ce qui est dans le cache, donc le cache reste correct.
Voici quelques scénarios courants où le cache devient invalide, mais zsh ne s'en rend pas compte.
- Vous ajoutez des fichiers à
$fpath
et supprimer exactement le même nombre de fichiers. - Vous renommez un fichier en
$fpath
. - Vous ajoutez ou modifiez le
#compdef
(ou#autoload
) ligne en haut du fichier.
Ce dernier point est ce qui a tendance à mordre lors des tests. Si vous modifiez le #compdef
ligne, vous devez supprimer le .zcompdump
fichier et redémarrez zsh (ou relancez compinit
).
Si vous placez des complétions dans un package redistribuable, déposez simplement le fichier de complétion dans un répertoire qui se trouve dans le système $fpath
. Pour un paquet Ubuntu, l'endroit approprié est /usr/share/zsh/vendor-completions
. Pour quelque chose installé sous /usr/local
, c'est /usr/local/share/zsh/site-functions
. C'est tout ce que vous avez à faire.
La seule chose qui n'est pas transparente, c'est si vous devez changer le #compdef
ligne dans une mise à niveau, ou si vous supprimez ou renommez certains fichiers. Dans de tels cas, les utilisateurs devront supprimer leur fichier de cache, et ce n'est pas quelque chose que vous pouvez faire à partir d'un package installé sur une machine multi-utilisateur.