È possibile utilizzare uno script di completamento con tabulazione Bash in zsh?


87

Ho uno script di completamento con tabulazioni Bash per Hadoop di Apache. Normalmente, utilizzo zsh come shell quotidiana. Tende ad essere piuttosto bash quando ne ho bisogno, ma sembra che i sistemi di completamento con tabulazione siano radicalmente diversi tra loro. C'è un modo semplice per "convertire" le definizioni di completamento bash-tab esistenti per lavorare in zsh? Non voglio investire un sacco di tempo in questo, ma se fosse facile risparmierei una quantità moderata di sforzi.

Risposte:


39

Da questa pagina (datata 2010/01/05):

Zsh può gestire le funzioni di completamento bash. L'ultima versione di sviluppo di zsh ha una funzione bashcompinit, che una volta eseguita consentirà a zsh di leggere le specifiche e le funzioni di completamento di bash. Questo è documentato nella pagina man zshcompsys. Per usarlo tutto quello che devi fare è eseguire bashcompinit in qualsiasi momento dopo compinit. Definirà le funzioni complete e compgen corrispondenti ai comandi incorporati bash.


La buona notizia: penso che dovrebbe funzionare, quindi grazie mille. La cattiva notizia: per qualche motivo, il sistema su cui sto cercando di farlo non sembra caricare / etc / zshrc quando accedo tramite SSH. Non so abbastanza sulla procedura di accesso per capire perché è così. Forse è tempo di fare un'altra domanda ...
Coderer

1
@Coderer: Prima di tutto, dici "/ etc / zshrc". Sul mio sistema, lo è /etc/zsh/zshrc. Inoltre, controllare i seguenti file in ordine inverso (elencati nell'ordine in cui vengono acquistati durante l'avvio zsh): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofilee $ZDOTDIR/.zprofile(probabilmente ~/.zprofile) per vedere se la RCSvariabile non è impostata. Se lo è, ciò impedirebbe la provenienza dei file successivi dopo il file in cui non è stato impostato. Infine, controlla la shell per l'utente /etc/passwde assicurati che sia zshe assicurati che non abbia un -fargomento.
In pausa fino a nuovo avviso.

Grazie per tutto il feedback - Ho fatto ricorso al classico hack del programmatore n. 1, "stdout debugging" (istruzioni echo in ogni script di avvio) e ho trovato il problema. Per qualche ragione, il nostro / etc / zprofile stava cercando i vari script /etc/profile.d, che venivano poi recuperati di nuovo in / etc / zshrc. Il semplice spostamento delle istruzioni di caricamento automatico all'inizio di / etc / zprofile ha risolto il problema.
Coderer

157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file

10
Questa è la risposta migliore poiché ti dice come usare bashcompinit. Bel lavoro.
pirospade

5
Grazie, ottima risposta, sfortunatamente questo non funziona se lo script usa il comando bash _init_completion.
0fnt

6
Questo non ha funzionato per me. Stavo ancora ricevendo un complete:13: command not found: compdeferrore.
Jatin Kumar

Se non funziona, controlla lo script (doh :)) - potrebbe avere un if is-bashsegno di spunta in alto.
olejorgenb

Questo non funziona per alcuni script _get_comp_words_by_refche utilizzano che non è definito da bashcompinit. Tuttavia, la maggior parte dei completamenti non utilizza questa funzione.
Franklin Yu

39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Sto eseguendo zsh zsh 5.0.2 (x86_64-apple-darwin13.0) senza ~ / .zshrc e la sequenza sopra ha funzionato in una shell zsh appena generata.

Grazie allo script git-completamento.bash per il suggerimento: D


Continua a leggere per maggiori dettagli sulle 3 righe precedenti:

Bash ha un fantastico supporto per il completamento automatico integrato, ma gli script di completamento automatico bash non funzionano direttamente su zsh poiché l'ambiente zsh non ha le funzioni essenziali di supporto per il completamento automatico di bash come compgen,complete . Lo fa nel tentativo di mantenere veloce la sessione di zsh.

In questi giorni zsh viene fornito con script di completamento appropriati come compinitebashcompinit che hanno le funzioni richieste per supportare gli script di completamento automatico bash.

autoload <func_name>: Nota che il caricamento automatico è definito in zsh e non in bash. autoloadcerca un file denominato nei percorsi di directory restituiti da fpathcomando e contrassegna una funzione da caricare la stessa quando viene invocata per la prima volta.

  • -U: Ignora qualsiasi alias durante il caricamento di una funzione come compinit o bashcompinit
  • + X: basta caricare la funzione denominata fow ora e non eseguirla

Ad esempio, sul mio sistema echo $fpathrestituisce /usr/share/zsh/site-functionse /usr/share/zsh/5.0.5/functionse entrambi compinite bashcompinitsono disponibili all'indirizzo /usr/share/zsh/5.0.5/functions.

Inoltre, per la maggior parte delle persone potrebbe essere autoload -U +X bashcompinit && bashcompinitrichiesto solo perché alcuni altri script come git autocomplete o il proprio ~/.zshrcpotrebbero essere autoload -U +X compinit && compiniteseguiti, ma è sicuro eseguirli entrambi.


Cosa sono -Ue +Xper?
jmk

Risposta aggiornata con maggiori dettagli.
Jatin Kumar

6
Questo ha ancora poco senso; la pagina di manuale descrive il punto di +X foofare lo stesso caricamento automatico solo invocando foo, ma senza eseguirlo immediatamente ... quindi autoload +X foo && foosembra completamente ridondante. Puoi spiegare perché hai scelto questo modello?
ELLIOTTCABLE

2
@ELLIOTTCABLE Il punto da fare autoload -U +X bashcompinit && bashcompinitè che (a causa del &&) eseguirà bashcompinitIFF il modulo è effettivamente trovato. Normale autoload foorestituisce sempre vero. Più tardi, quando si tenta di eseguire foo, poi zsh infine si dice "file di definizione di funzione non trovato". Con autoload +Xottieni immediatamente l'errore.
FeRD

1
La pagina man è ancora un po 'poco chiara su questo punto, mi sembra: autoload +Xcarica la funzione senza eseguirla - che è più di quanto autoloadfa, senza +X. Senza +X, il caricamento automatico non carica nemmeno la funzione; Contrassegna semplicemente il nome come riferimento a una funzione da caricare in seguito. Il caricamento effettivo non viene tentato fino a quando la funzione non viene prima richiamata. Se si desidera determinare se la funzione denominata viene caricata correttamente , è necessario utilizzare +Xper eseguire immediatamente la fase di caricamento.
FeRD

4

Per zshuso:

  • compdef
  • compadd

Il mio esempio:

# 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

Fonte: il mio codice https://github.com/reduardo7/bashx


1
Dovresti dichiarare di essere l'autore del framework bashx collegato.
Ben

4

Sto eseguendo Antigen come gestore di plugin Oh-My-Zsh. Avevo alcuni script di completamento bash scritti da colleghi che volevo caricare in Zsh con un semplice file source /path/to/completion.

Ho avuto qualche problema, perché sembra che Antigen o OMZ (difficile da dire) si preoccupino solo del caricamento degli script di completamento dai loro plugin. Alla fine ho risolto il problema caricando automaticamente bashcompinit e compinit dopo antigen apply. Il semplice caricamento automatico bashcompinitnon era sufficiente.

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 crea il suo .zcompdumpfile in $ANTIGEN_COMPDUMPcui per me era~/.antigen/.zcompdump

La reinvocazione di compinit e bashcompinit crea un secondo .zcompdump in $HOME/.zcompdump

Questo sembra per tutto il lavoro fuori, perché sono in grado di utilizzare i completamenti istituiti da /path/to/bash_completion. Ho cancellato entrambi i file .zcompdump alcune volte per assicurarmi che siano rigenerati e sembrino funzionare.

Ho dovuto eseguire il rm dei file .zcompdump alcune volte dopo il riavvio di una macchina a causa di errori generati durante il tentativo di completare la scheda, ma non sono sicuro che ciò sia dovuto a questa configurazione o qualcos'altro. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPe una nuova shell lo risolve per me.

Versioni utilizzate al momento della scrittura:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3

0

La risposta di @ JatinKumar mi ha portato sulla strada giusta, ma ho dovuto usare al completeposto di source. Quindi tutti insieme:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.