Czy skrypt uzupełniania tabulatorów Bash może być używany w zsh?

87

Mam skrypt uzupełniania kart Bash dla Hadoop Apache. Zwykle używam zsh jako mojej powłoki na co dzień. Wydaje się, że jest całkiem podobny do basha, kiedy tego potrzebuję, ale wygląda na to, że systemy uzupełniania zakładek są między nimi radykalnie różne. Czy istnieje prosty sposób na „konwersję” istniejących definicji uzupełniania bash-tab do pracy w zsh? Nie chcę inwestować w to mnóstwa czasu, ale gdyby było to łatwe, zaoszczędziłbym trochę wysiłku.

Coderer
źródło

Odpowiedzi:

39

Z tej strony (z dnia 2010/01/05):

Zsh może obsługiwać funkcje uzupełniania bash. Najnowsza wersja rozwojowa zsh ma funkcję bashcompinit, która po uruchomieniu pozwoli zsh odczytać specyfikacje i funkcje uzupełniania bash. Jest to udokumentowane na stronie podręcznika zshcompsys. Aby go użyć, wystarczy uruchomić bashcompinit w dowolnym momencie po compinit. Zdefiniuje funkcje complete i compgen odpowiadające wbudowanym funkcjom bash.

Wstrzymano do odwołania.
źródło
Dobra wiadomość: myślę, że to powinno działać, więc wielkie dzięki. Zła wiadomość: z jakiegoś powodu system, na którym próbuję to osiągnąć, nie ładuje / etc / zshrc, kiedy loguję się przez SSH. Nie wiem wystarczająco dużo o procesie logowania, aby powiedzieć, dlaczego tak się dzieje. Może czas zadać kolejne pytanie ...
Coderer
1
@Coderer: Przede wszystkim mówisz "/ etc / zshrc". W moim systemie to jest /etc/zsh/zshrc. Należy także sprawdzić następujące pliki w odwrotnej kolejności (wymienione w kolejności, w jakiej są pozyskiwane podczas uruchamiania zsh) /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofileoraz $ZDOTDIR/.zprofile(prawdopodobnie~/.zprofile ), aby sprawdzić, czy RCSzmienna jest ustawiona. Jeśli tak, uniemożliwiłoby to pobieranie kolejnych plików po pliku, w którym nie jest ustawiony. Na koniec sprawdź, czy w powłoce znajduje się użytkownik, /etc/passwdi upewnij zshsię, że nie ma -fargumentu.
Wstrzymano do odwołania.
Dziękuję za wszystkie opinie - uciekłem się do # 1 klasycznego hacka dla programistów, „debugowania standardowego” (instrukcje echa w każdym skrypcie startowym) i znalazłem problem. Z jakiegoś powodu nasz / etc / zprofile pobierał różne skrypty /etc/profile.d, które były następnie ponownie pobierane w / etc / zshrc. Po prostu przeniesienie instrukcji automatycznego ładowania na początek / etc / zprofile rozwiązało problem.
Coderer,
157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
freestyler
źródło
10
To jest lepsza odpowiedź, ponieważ mówi, jak używać bashcompinit. Dobra robota.
pirospada
5
Dzięki, świetna odpowiedź, niestety to nie działa, jeśli skrypt używa polecenia bash _init_completion.
0fnt
6
To nie zadziałało dla mnie. Nadal otrzymywałem complete:13: command not found: compdefbłąd.
Jatin Kumar,
Jeśli to nie zadziała, sprawdź skrypt (doh :)) - może mieć if is-bashcheck na górze.
olejorgenb
To nie działa w przypadku niektórych skryptów, _get_comp_words_by_refktóre nie są zdefiniowane przez bashcompinit. Większość uzupełnień nie używa jednak tej funkcji.
Franklin Yu
39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Uruchamiam zsh zsh 5.0.2 (x86_64-apple-darwin13.0) bez ~ / .zshrc i powyższa sekwencja działała w świeżo utworzonej powłoce zsh.

Dzięki skryptowi git-complete.bash za podpowiedź: D


Czytaj dalej, aby uzyskać więcej informacji na temat powyższych 3 wierszy:

Bash ma niesamowite wsparcie w wybudowanym zakończenia auto ale skrypty bash autouzupełniania nie działają bezpośrednio zsh zsh jako środowisko nie mają istotnego bash autouzupełniania funkcje pomocnicze podoba compgen, complete. Robi to, aby sesja zsh była szybka.

Obecnie zsh jest dostarczany z odpowiednimi skryptami ukończenia, takimi jak compinit i, bashcompinitktóre mają wymagane funkcje do obsługi skryptów autouzupełniania bash.

autoload <func_name>: Zauważ, że automatyczne ładowanie jest zdefiniowane w zsh, a nie w bash. autoloadszuka pliku o nazwie w ścieżkach katalogów zwróconych przez fpathpolecenie i zaznacza funkcję, która ma załadować to samo, gdy jest po raz pierwszy wywoływana.

  • -U: Ignoruj ​​aliasy podczas ładowania funkcji, takich jak compinit lub bashcompinit
  • + X: Po prostu załaduj teraz nazwaną funkcję fow i nie wykonuj jej

Na przykład w moim systemie echo $fpathzwraca /usr/share/zsh/site-functionsi /usr/share/zsh/5.0.5/functionsi oba compinitibashcompinit są dostępne /usr/share/zsh/5.0.5/functions.

Również dla większości ludzi może to być autoload -U +X bashcompinit && bashcompinitwymagane tylko dlatego, że jakiś inny skrypt, taki jak autouzupełnianie git lub ich własny, ~/.zshrcmoże działać autoload -U +X compinit && compinit, ale można bezpiecznie po prostu uruchomić oba z nich.

Jatin Kumar
źródło
Co jest -Ui +Xdo czego?
jmk
Zaktualizowana odpowiedź zawierająca więcej szczegółów.
Jatin Kumar,
6
To wciąż nie ma sensu; strona podręcznika opisuje cel, w +X foojakim robi to samo automatyczne ładowanie, co tylko wywołanie foo, ale bez natychmiastowego wykonania tego… autoload +X foo && foowydaje się więc całkowicie zbędne. Czy możesz wyjaśnić, dlaczego wybrałeś ten wzór?
ELLIOTTCABLE
2
@ELLIOTTCABLE Chodzi o autoload -U +X bashcompinit && bashcompinitto, że (ze względu na &&) wykona bashcompinitIFF faktycznie znaleziony moduł. Normalny autoload foozawsze zwraca prawdę. Później, gdy próbujesz uruchomić foo, a następnie zsh wreszcie powie „funkcja plik definicji nie znaleziono”. Dzięki autoload +Xtemu natychmiast otrzymasz błąd.
FeRD
1
Wydaje mi się, że strona autoload +Xpodręcznika jest nadal nieco niejasna w tej kwestii: ładuje funkcję bez jej wykonywania - co jest więcej niż autoloadbez niej +X. Bez +Xautoloada nawet nie wczytuje funkcji; Po prostu oznacza nazwę jako odwołującą się do funkcji, która ma zostać załadowana później. Rzeczywiste ładowanie nie jest podejmowane, dopóki funkcja nie zostanie po raz pierwszy wywołana. Jeśli chcesz ustalić, czy nazwana funkcja została pomyślnie załadowana, musisz użyć jej +Xdo natychmiastowego wykonania kroku ładowania.
FeRD
4

Do zshużycia:

  • compdef
  • compadd

Mój przykład:

# 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

Źródło: Mój kod https://github.com/reduardo7/bashx

Eduardo Cuomo
źródło
1
Powinieneś ujawnić, że jesteś autorem połączonego frameworka bashx.
Ben
4

Używam programu Antigen jako menedżera wtyczek Oh-My-Zsh. Miałem kilka skryptów ukończenia basha napisanych przez współpracowników, które chciałem załadować do Zsh za pomocą prostego source /path/to/completion.

Miałem pewne problemy, ponieważ wydaje się, że albo Antigen, albo OMZ (trudno powiedzieć) zajmują się tylko ładowaniem skryptów uzupełniania z ich wtyczek. W końcu udało mi się to obejść przez automatyczne ładowanie bashcompinit i compinit później antigen apply. Samo automatyczne ładowanie bashcompinitnie wystarczyło.

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

Antygen tworzy swój .zcompdumpplik w $ANTIGEN_COMPDUMPktórym był dla mnie~/.antigen/.zcompdump

Ponowne wywołanie compinit i bashcompinit powoduje utworzenie drugiego pliku .zcompdump w $HOME/.zcompdump

Że wydaje się , aby wszystko się uda, bo jestem w stanie wykorzystać uzupełnień utworzonych przez /path/to/bash_completion. Kilka razy usunąłem oba pliki .zcompdump, aby upewnić się, że zostały ponownie wygenerowane i wydają się działać.

Musiałem kilka razy rmować pliki .zcompdump po ponownym uruchomieniu komputera z powodu błędów wyświetlanych podczas próby zakończenia zakładki, ale nie jestem pewien, czy to z powodu tej konfiguracji, czy czegoś innego. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPa nowa powłoka naprawia to za mnie.

Wersje używane w czasie pisania:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Walter Wilfinger
źródło
0

Odpowiedź @ JatinKumar zaprowadziła mnie na właściwą ścieżkę, ale completezamiast tego musiałem użyć source. Więc wszyscy razem:

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
źródło