Un script de complétion de tabulation Bash peut-il être utilisé dans zsh?

87

J'ai un script de complétion de tabulation Bash pour Hadoop d'Apache. Normalement, j'utilise zsh comme shell au quotidien. Cela a tendance à être plutôt bash quand j'en ai besoin, mais il semble que les systèmes de complétion par onglets soient radicalement différents entre eux. Existe-t-il un moyen simple de "convertir" les définitions de complétion bash-tab-complétion existantes pour qu'elles fonctionnent dans zsh? Je ne veux pas y investir beaucoup de temps, mais si c'est facile, j'économiserais un effort modéré.

Codeur
la source

Réponses:

39

À partir de cette page (datée du 05/01/2010):

Zsh peut gérer les fonctions de complétions bash. La dernière version de développement de zsh a une fonction bashcompinit, qui, lorsqu'elle est exécutée, permettra à zsh de lire les spécifications et les fonctions d'achèvement de bash. Ceci est documenté dans la page de manuel zshcompsys. Pour l'utiliser, il vous suffit d'exécuter bashcompinit à tout moment après compinit. Il définira les fonctions complete et compgen correspondant aux fonctions intégrées bash.

Suspendu jusqu'à nouvel ordre.
la source
La bonne nouvelle: je pense que cela devrait fonctionner, alors merci beaucoup. La mauvaise nouvelle: pour une raison quelconque, le système sur lequel j'essaie d'accomplir cela ne semble pas charger / etc / zshrc lorsque je me connecte via SSH. Je ne connais pas assez le processus de connexion pour expliquer pourquoi c'est le cas. Peut-être qu'il est temps de poser une autre question ...
Coderer
1
@Coderer: Tout d'abord, vous dites "/ etc / zshrc". Sur mon système, c'est /etc/zsh/zshrc. En outre, vérifiez les fichiers suivants dans l' ordre inverse ( voir la liste dans l'ordre où ils sont achetés au démarrage zsh): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofileet $ZDOTDIR/.zprofile(probablement ~/.zprofile) pour voir si la RCSvariable est hors service. Si tel est le cas, cela empêcherait la source des fichiers suivants après le fichier dans lequel il est désactivé. Enfin, vérifiez le shell de l'utilisateur /etc/passwdet assurez-vous qu'il est zshet assurez-vous qu'il n'a pas d' -fargument.
Suspendu jusqu'à nouvel ordre.
Merci pour tous les commentaires - j'ai eu recours au piratage de programmeur classique n ° 1, le "débogage stdout" (instructions d'écho dans chaque script de démarrage) et j'ai trouvé le problème. Pour une raison quelconque, notre / etc / zprofile recherchait les divers scripts /etc/profile.d, qui étaient ensuite à nouveau extraits dans / etc / zshrc. Le simple fait de déplacer les instructions de chargement automatique en haut de / etc / zprofile a résolu le problème.
Coderer
157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
freestyler
la source
10
C'est la meilleure réponse car elle vous indique comment utiliser bashcompinit. Bon travail.
pyrospade
5
Merci, bonne réponse, malheureusement cela ne fonctionne pas si le script utilise la commande _init_completion bash.
0fnt
6
Cela n'a pas fonctionné pour moi. J'obtenais toujours une complete:13: command not found: compdeferreur.
Jatin Kumar
Si cela ne fonctionne pas, vérifiez le script (doh :)) - il peut y avoir une if is-bashcoche en haut.
olejorgenb
Cela ne fonctionne pas pour certains scripts _get_comp_words_by_refqui ne sont pas définis par bashcompinit. Cependant, la plupart des complétions n'utilisent pas cette fonction.
Franklin Yu le
39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

zsh 5.0.2 (x86_64-apple-darwin13.0) J'exécute zsh sans aucun ~ / .zshrc et la séquence ci-dessus a fonctionné dans un shell zsh fraîchement généré.

Merci au script git-completion.bash pour l'indice: D


Lisez la suite pour plus de détails sur les 3 lignes ci-dessus:

Bash impressionnant à l' appui construit auto complétion , mais les scripts bash autocomplete ne zsh directement fonctionne pas comme environnement zsh ne pas les fonctions d'aide bash essentielle autocomplete aiment compgen, complete. Il le fait dans un effort pour garder la session zsh rapide.

Ces jours-ci, zsh est livré avec des scripts de complétion appropriés comme compinitet bashcompinitqui ont les fonctions requises pour prendre en charge les scripts de saisie semi-automatique bash.

autoload <func_name>: Notez que le chargement automatique est défini dans zsh et non dans bash. autoloadrecherche un fichier nommé dans les chemins de répertoire renvoyés par la fpathcommande et marque une fonction pour la charger lors de son premier appel.

  • -U: ignore les alias lors du chargement d'une fonction comme compinit ou bashcompinit
  • + X: il suffit de charger la fonction nommée maintenant et de ne pas l'exécuter

Par exemple sur mon système echo $fpathrenvoie /usr/share/zsh/site-functionset /usr/share/zsh/5.0.5/functionset les deuxcompinit et bashcompinitsont disponibles sur /usr/share/zsh/5.0.5/functions.

De plus, pour la plupart des gens, ce n'est peut-être autoload -U +X bashcompinit && bashcompinitnécessaire que parce qu'un autre script comme git autocomplete ou le leur ~/.zshrcpeut le faire autoload -U +X compinit && compinit, mais il est prudent de les exécuter tous les deux.

Jatin Kumar
la source
Que sont -Uet +Xpour quoi ?
jmk
Réponse mise à jour avec plus de détails.
Jatin Kumar
6
Cela n'a toujours pas de sens; la page de manuel décrit le point de +X foofaire le même chargement automatique que l'invocation foo, mais sans l'exécuter immédiatement… autoload +X foo && foosemble donc complètement redondant. Pouvez-vous expliquer pourquoi vous avez choisi ce modèle?
ELLIOTTCABLE
2
@ELLIOTTCABLE Le but de faire autoload -U +X bashcompinit && bashcompinitest que (en raison de la &&) il exécutera bashcompinitIFF le module est réellement trouvé. Normal autoload foorenvoie toujours vrai. Plus tard, quand vous essayez d'exécuter foo, puis zsh enfin vous dit « fichier de définition de fonction not found ». Avec autoload +Xvous obtenez l'erreur immédiatement.
FeRD
1
La page de manuel est encore un peu floue sur ce point, il me semble: autoload +Xcharge la fonction sans l'exécuter - ce qui est plus que autoloadne le fait, sans +X. Sans +X, le chargement automatique ne charge même pas la fonction; Il marque simplement le nom comme faisant référence à une fonction à charger ultérieurement. Le chargement réel n'est pas tenté tant que la fonction n'est pas appelée pour la première fois. Si vous souhaitez déterminer si la fonction nommée se charge correctement , vous devez utiliser +Xpour effectuer immédiatement l'étape de chargement.
FeRD
4

Pour zshutilisation:

  • compdef
  • compadd

Mon exemple:

# bash completion for bxrun (/home/ecuomo/projects/bashx/bxrun)
_bxrun_methods() {
    grep "^\s*\(function\s\+\)\?__.\+()\s*{.*$" "${1}" | while read line ; do
        echo "$line" | sed "s/()\s*{.*//g" | sed "s/\s*\(function\s\+\)\?__//g"
    done
}
_bxrun_lst() {
    if [ -d "/home/ecuomo/projects/bashx/src/actions" ]; then
        for f in /home/ecuomo/projects/bashx/src/actions/* ; do
            if [ -f "${f}" ]; then
                basename "${f}" | sed 's/\..*$//g'
            fi
        done
    fi
    _bxrun_methods "/home/ecuomo/projects/bashx/bxrun"
    _bxrun_methods "/home/ecuomo/projects/bashx/src/bashx.sh"
}
_bxrun() {
    local cur
    COMPREPLY=()
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $( compgen -W '$( _bxrun_lst )' -- $cur  ) )
}
_bxrun_zsh() {
    compadd `_bxrun_lst`
}
if type complete >/dev/null 2>/dev/null; then
    # bash
    complete -F _bxrun bxrun
else if type compdef >/dev/null 2>/dev/null; then
    # zsh
    compdef _bxrun_zsh bxrun
fi; fi

Source: Mon code https://github.com/reduardo7/bashx

Eduardo Cuomo
la source
1
Vous devez indiquer que vous êtes l'auteur du framework bashx lié.
Ben
4

J'utilise Antigen en tant que gestionnaire de plugins Oh-My-Zsh. J'ai eu quelques scripts de complétion bash écrits par des collègues que je voulais charger dans Zsh avec un simplesource /path/to/completion .

J'ai eu quelques problèmes, car il semble qu'Antigen ou OMZ (difficile à dire) se préoccupent uniquement du chargement des scripts de complétion à partir de leurs plugins. J'ai finalement contourné cela en chargeant automatiquement bashcompinit et compinit après antigen apply. Le chargement automatique bashcompinitne suffisait pas.

source ~/.antigen/antigen.zsh
antigen use oh-my-zsh
antigen apply

autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit

source /path/to/bash_completion

Antigen crée son .zcompdumpfichier $ANTIGEN_COMPDUMPauquel pour moi était~/.antigen/.zcompdump

La ré-invocation de compinit et bashcompinit crée un second .zcompdump à $HOME/.zcompdump

Tout cela semble fonctionner, car je peux utiliser les complétions configurées par /path/to/bash_completion. J'ai supprimé les deux fichiers .zcompdump plusieurs fois pour m'assurer qu'ils sont régénérés et semblent fonctionner.

J'ai dû rm les fichiers .zcompdump plusieurs fois après un redémarrage de la machine en raison d'erreurs générées lors de la tentative de tabulation complète, mais je ne sais pas si cela est dû à cette configuration ou à autre chose. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPet un nouveau shell corrige cela pour moi.

Versions utilisées au moment de la rédaction:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Walter Wilfinger
la source
0

La réponse de @ JatinKumar m'a mis sur la bonne voie, mais j'ai dû utiliser à la completeplace de source. Donc tous ensemble:

autoload -Uz compinit && compinit
autoload -U +X bashcompinit && bashcompinit

complete -C /usr/local/bin/terraform terraform
complete -C /usr/local/aws/bin/aws_completer aws
complete -C /usr/local/bin/az az
jschmitter
la source