Kann ein Bash-Tab-Vervollständigungsskript in zsh verwendet werden?

87

Ich habe ein Bash-Tab-Vervollständigungsskript für Apaches Hadoop. Normalerweise verwende ich zsh als meine tägliche Shell. Es neigt dazu, ziemlich bashartig zu sein, wenn ich es brauche, aber es sieht so aus, als ob sich die Tab-Vervollständigungssysteme zwischen ihnen radikal unterscheiden. Gibt es eine einfache Möglichkeit, die vorhandenen Definitionen für die Vervollständigung von Bash-Tabs in zsh zu "konvertieren"? Ich möchte nicht viel Zeit in diese Sache investieren, aber wenn es einfach ist, würde ich einen moderaten Aufwand sparen.

Codierer
quelle

Antworten:

39

Von dieser Seite (vom 05.01.2010):

Zsh kann Bash-Vervollständigungsfunktionen ausführen. Die neueste Entwicklungsversion von zsh verfügt über eine Funktion bashcompinit, mit der zsh beim Ausführen die Spezifikationen und Funktionen zum Abschluss der Bash lesen kann. Dies ist in der Manpage von zshcompsys dokumentiert. Um es zu verwenden, müssen Sie bashcompinit jederzeit nach compinit ausführen. Es werden vollständige und compgen-Funktionen definiert, die den eingebauten Bash-Funktionen entsprechen.

Bis auf weiteres angehalten.
quelle
Die gute Nachricht: Ich denke, das sollte funktionieren, also vielen Dank. Die schlechte Nachricht: Aus irgendeinem Grund scheint das System, auf dem ich dies erreichen möchte, / etc / zshrc nicht zu laden, wenn ich mich über SSH anmelde. Ich weiß nicht genug über den Anmeldevorgang, um zu sagen, warum dies der Fall ist. Vielleicht ist es Zeit, eine andere Frage zu stellen ...
Coderer
1
@Coderer: Zuerst sagst du "/ etc / zshrc". Auf meinem System ist es /etc/zsh/zshrc. Überprüfen Sie auch die folgenden Dateien in umgekehrter Reihenfolge (aufgeführt in der Reihenfolge , wie sie während des zsh Start bezogen werden): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofileund $ZDOTDIR/.zprofile(wahrscheinlich ~/.zprofile) zu sehen , ob die RCSVariable nicht gesetzt ist. Wenn dies der Fall ist, wird verhindert, dass die nachfolgenden Dateien nach der Datei, in der sie nicht festgelegt wurden, bezogen werden. Überprüfen Sie abschließend die Shell für den Benutzer /etc/passwdund stellen Sie sicher, dass sie vorhanden ist zshund dass sie kein -fArgument enthält.
Bis auf weiteres angehalten.
Vielen Dank für all das Feedback. Ich habe auf den klassischen Programmierer-Hack Nr. 1 zurückgegriffen, "stdout debugging" (Echo-Anweisungen in jedem Startskript) und das Problem gefunden. Aus irgendeinem Grund bezog unser / etc / zprofile die verschiedenen /etc/profile.d-Skripte, die dann erneut in / etc / zshrc bezogen wurden. Durch einfaches Verschieben der Autoload-Anweisungen an den Anfang von / etc / zprofile wurde das Problem behoben.
Coderer
152
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
Freestyler
quelle
9
Dies ist die bessere Antwort, da hier erfahren wird, wie Sie bashcompinit verwenden. Gut gemacht.
Pyrospade
5
Danke, tolle Antwort, leider funktioniert dies nicht, wenn das Skript den Befehl _init_completion bash verwendet.
0fnt
5
Das hat bei mir nicht funktioniert. Ich bekam immer noch complete:13: command not found: compdefFehler.
Jatin Kumar
Wenn es nicht funktioniert, überprüfen Sie das Skript (doh :)) - möglicherweise befindet sich oben eine if is-bashÜberprüfung.
Olejorgenb
Dies funktioniert nicht für einige Skripte, _get_comp_words_by_refdie nicht durch definiert sind bashcompinit. Die meisten Vervollständigungen verwenden diese Funktion jedoch nicht.
Franklin Yu
38
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Ich zsh 5.0.2 (x86_64-apple-darwin13.0) führe zsh ohne ~ / .zshrc aus und die obige Sequenz hat in einer frisch erzeugten zsh-Shell funktioniert.

Danke an git-vervollständigung.bash Skript für den Hinweis: D.


Lesen Sie weiter für weitere Details zu den obigen 3 Zeilen:

Bash hat eingebaute automatische Vervollständigung Unterstützung genial , aber der Bash - Skripte zum automatischen Vervollständigung funktioniert nicht direkt zsh als zsh Umgebung nicht die wesentliche bash zum automatischen Vervollständigung Hilfsfunktionen wie compgen, complete. Dies geschieht, um die zsh-Sitzung schnell zu halten.

In diesen Tagen ZSH mit entsprechendem Abschluss - Skripte wie ausgeliefert wird compinitund bashcompinitwelche die erforderlichen Funktionen zur Unterstützung Bash - Skripte zum automatischen Vervollständigung.

autoload <func_name>: Beachten Sie, dass das automatische Laden in zsh und nicht in bash definiert ist. autoloadSucht nach einer Datei mit dem Namen in den vom fpathBefehl zurückgegebenen Verzeichnispfaden und markiert eine Funktion, die beim ersten Aufruf geladen werden soll.

  • -U: Ignoriere alle Aliase, wenn du eine Funktion wie compinit oder bashcompinit lädst
  • + X: Laden Sie jetzt einfach die benannte Funktion fow und führen Sie sie nicht aus

Zum Beispiel auf meinem System echo $fpathzurückgegeben /usr/share/zsh/site-functionsund /usr/share/zsh/5.0.5/functionsund beide compinitund bashcompinitsind verfügbar bei /usr/share/zsh/5.0.5/functions.

Auch für die meisten Menschen nur sein kann ist autoload -U +X bashcompinit && bashcompiniterforderlich, weil einige andere Skript wie git oder die automatische Vervollständigung ihrer eigenen ~/.zshrckann tun autoload -U +X compinit && compinit, aber es ist sicher nur sie beide laufen.

Jatin Kumar
quelle
Was sind -Uund +Xwofür?
JMK
Aktualisierte Antwort mit weiteren Details.
Jatin Kumar
6
Das macht immer noch wenig Sinn; Die Manpage beschreibt den Punkt +X foo, dass das gleiche automatische Laden wie beim Aufrufen ausgeführt foowird, ohne es jedoch sofort auszuführen. Dies autoload +X foo && fooscheint also völlig überflüssig zu sein. Können Sie erklären, warum Sie dieses Muster gewählt haben?
ELLIOTTCABLE
1
@ELLIOTTCABLE Der Punkt autoload -U +X bashcompinit && bashcompinitist, dass (aufgrund der &&) bashcompinitIFF ausgeführt wird, wenn das Modul tatsächlich gefunden wird. Normal gibt autoload fooimmer true zurück. Später, wenn Sie ausführen versuchen foo, dann schließlich zsh sagen Sie „Funktion Definitionsdatei nicht gefunden“. Mit erhalten autoload +XSie den Fehler sofort.
FeRD
1
Die Manpage ist in diesem Punkt noch etwas unklar, scheint mir: autoload +XLädt die Funktion, ohne sie auszuführen - was mehr ist als autoloadohne +X. Ohne lädt +XAutoload die Funktion nicht einmal ; Der Name verweist lediglich auf eine Funktion, die später geladen werden soll. Das eigentliche Laden wird erst versucht, wenn die Funktion zum ersten Mal aufgerufen wird. Wenn Sie feststellen möchten, ob die genannte Funktion erfolgreich geladen wurde, müssen Sie +Xden Ladeschritt sofort ausführen.
FeRD
4

Zur zshVerwendung:

  • compdef
  • compadd

Mein Beispiel:

# 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

Quelle: Mein Code https://github.com/reduardo7/bashx

Eduardo Cuomo
quelle
1
Sie sollten angeben, dass Sie der Autor des verknüpften bashx-Frameworks sind.
Ben
4

Ich verwende Antigen als Oh-My-Zsh-Plugin-Manager. Ich hatte ein paar Bash-Vervollständigungsskripte von Kollegen geschrieben, die ich mit einem einfachen in Zsh laden wollte source /path/to/completion.

Ich hatte einige Probleme, weil es so aussieht, als ob Antigen oder OMZ (schwer zu sagen) sich nur darum kümmern, Abschlussskripte von ihren Plugins zu laden. Ich habe das endlich durch Autoloading bashcompinit und compinit danach umgangen antigen apply. Nur das automatische Laden bashcompinitwar nicht genug.

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 erstellt seine .zcompdumpDatei, bei $ANTIGEN_COMPDUMPder für mich war~/.antigen/.zcompdump

Durch das erneute Aufrufen von compinit und bashcompinit wird ein zweiter .zcompdump bei erstellt $HOME/.zcompdump

Das scheint alles zu klappen, denn ich kann die von eingerichteten Vervollständigungen verwenden /path/to/bash_completion. Ich habe beide .zcompdump-Dateien einige Male gelöscht, um sicherzustellen, dass sie neu generiert werden und anscheinend funktionieren.

Ich musste die .zcompdump-Dateien einige Male nach einem Neustart des Computers speichern, da beim Versuch, die Registerkarte zu vervollständigen, Fehler aufgetreten sind. Ich bin mir jedoch nicht sicher, ob dies auf diese Einrichtung oder auf etwas anderes zurückzuführen ist. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPund eine neue Shell behebt das für mich.

Zum Zeitpunkt des Schreibens verwendete Versionen:

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