Bitte verzeihen Sie mir, wenn ich hier etwas Dummes mache, die Dokumentation ist riesig und die Suche hat noch nichts ergeben.
Ich versuche, Shell-Vervollständigungen für mein benutzerdefiniertes Skript namens fab
zu erstellen . Für Bash war es einfach, sie einfach in /etc/bash_completion.d
abzulegen und sie funktionieren. Aber oh Mann, ist zsh ein PITA…
Ich habe die Vervollständigungsfunktion _fab
und es funktioniert gut, wenn es mit compdef _fab fab
aktiviert wird . Ich habe es in /usr/share/zsh/vendor-completions/_fab
abgelegt was bereits in meinem $fpath
war . Die Datei beginnt mit #compdef fab
und endet mit compdef _fab fab
. Sieht gut aus:
$ type _fab
_fab is an autoload shell function
Aber immer wenn ich eine neue Shell gestartet habe, fab
Vervollständigungen funktionierten nicht (andere Funktionen von vendor-completions
, wie _docker
, uns geht es gut). compinit
dies wurde für diese bestimmte Shell behoben. Ich habe herausgefunden, dass rm ~/.zcompdump ~/.zcompdump-$(hostname)-5.1.1; compinit
dauerhaft funktionieren lassen (5.1.1 =meine zsh-Version).
Fragen:
- Was und wann liest
~/.zcompdump
erste Vervollständigungen einrichten? -
man zshall
sagt:Der nächste Aufruf von compinit wird die ausgegebene Datei lesen, anstatt eine vollständige Initialisierung durchzuführen.
Wenn das der Fall war,
compinit
würde meine Vervollständigungen nicht reparieren, bevor ich~/.zcompdump
gelöscht habe , Rechts? Übersehe ich etwas? - Was ist
~/.zcompdump-$(hostname)-5.1.1
und wie hängt es mit.zcompdump
zusammen ? Der einzige Unterschied ist eine Vervollständigung, die sich in~/.oh-my-zsh/completions
befindet (weil$ZSH
zeigt auf~/.oh-my-zsh
). Ist es eine Oh-mein-zsh-Sache? - Wenn ich diese Vervollständigungen in ein verteilbares Paket packen oder ein Installationsskript erstellen würde, wo sollte ich zsh-Vervollständigungen platzieren und was sollte ich während der Installation sonst noch tun, um sicherzustellen, dass alles funktioniert?
Ich ziele auf Ubuntu 16.04, 18.04 und 19.04 ab, aber nicht-distrospezifische Informationen sind willkommen. Ich teste dies auf Ubuntu 16.04 mit zsh 5.1.1 und dem aktuellen oh-my-zsh.
Akzeptierte Antwort:
TL,DR:Legen Sie die Datei im normalen Betrieb einfach im entsprechenden Verzeichnis ab. Während des Tests müssen Sie die Cache-Datei (.zcompdump
standardmäßig, aber Benutzer können es an einem anderen Ort ablegen, und oh-my-zsh legt es an einem anderen Ort ab).
Die einfache Antwort ist, die Vervollständigungsfunktion in eine Datei zu schreiben, in der die erste Zeile #compdef fab
ist . Die Datei muss sich in einem Verzeichnis auf $fpath
befinden .
Die Datei kann entweder den Funktionsrumpf oder eine Definition der Funktion gefolgt von einem Aufruf der Funktion enthalten. Das heißt, entweder enthält die Datei etwas wie
#compdef fab
_arguments …
oder
#compdef fab
function _fab {
_arguments …
}
_fab "[email protected]"
Die Datei muss auf $fpath
vorhanden sein vor compinit
läuft. Das bedeutet, dass Sie auf die Reihenfolge in .zshrc
achten müssen :Fügen Sie zuerst alle benutzerdefinierten Verzeichnisse zu $fpath
hinzu , dann rufen Sie compinit
auf . Wenn Sie ein Framework wie oh-my-zsh verwenden, stellen Sie sicher, dass Sie alle benutzerdefinierten Verzeichnisse zu $fpath
hinzufügen vor dem oh-my-zsh-Code.
compinit
ist die Funktion, die das Vervollständigungssystem initialisiert. Es liest alle Dateien in $fpath
und überprüft ihre erste Zeile auf magische Direktiven #autoload
und #compdef
.
.zcompdump
ist eine Cache-Datei, die von compinit
verwendet wird . ~/.zcompdump
ist der Standardspeicherort; Sie können beim Ausführen von compinit
einen anderen Speicherort auswählen . Oh-my-zsh ruft compinit
auf mit dem -d
Option, einen anderen Cache-Dateinamen zu verwenden, der durch die Variable ZSH_COMPDUMP
angegeben wird , die standardmäßig
ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
Der Hostname ist für Personen enthalten, deren Home-Verzeichnis von mehreren Computern gemeinsam genutzt wird und die möglicherweise unterschiedliche Software auf verschiedenen Computern installiert haben. Die zsh-Version ist enthalten, weil die Cache-Datei zwischen den Versionen nicht kompatibel ist (sie enthält Code, der sich von Version zu Version ändert).
Verwandte:Was macht STRG + V in vim?
Ich denke, alle Ihre Probleme sind auf eine veraltete Cache-Datei zurückzuführen (und das hat Sie die Situation zu kompliziert gemacht). Leider ist der Algorithmus von zsh, um festzustellen, ob die Cache-Datei veraltet ist, nicht perfekt, vermutlich im Interesse der Geschwindigkeit. Es überprüft nicht den Inhalt oder die Zeitstempel der Dateien auf $fpath
, es zählt sie einfach. Ein .zcompdump
Datei beginnt mit einer Zeile wie
#files: 858 version: 5.1.1
Wenn die zsh-Version und die Anzahl der Dateien korrekt sind, lädt zsh die Cache-Datei.
Die Cache-Datei enthält nur Zuordnungen zwischen Befehlsnamen, nicht den Code von Abschlussfunktionen. Hier sind einige gängige Szenarien, in denen der Cache transparent arbeitet:
- Wenn Sie
$fpath
eine neue Datei hinzufügen , dadurch wird der Cache ungültig. - Allgemeiner gesagt, wenn Sie Dateien auf
$fpath
hinzufügen und entfernen , und die Gesamtzahl der entfernten Dateien nicht mit der Gesamtzahl der entfernten Dateien übereinstimmt, macht dies den Cache ungültig. - Wenn Sie eine Datei in
$fpath
in ein anderes Verzeichnis verschieben ohne seinen Namen zu ändern, wirkt sich dies nicht auf alles aus, was sich im Cache befindet, sodass der Cache korrekt bleibt. - Wenn Sie eine Datei in
$fpath
ändern ohne die erste Zeile zu ändern, wirkt sich dies nicht auf den Cache aus, sodass der Cache korrekt bleibt.
Hier sind einige häufige Szenarien, in denen der Cache ungültig wird, aber zsh es nicht bemerkt.
- Sie fügen einige Dateien zu
$fpath
hinzu und genau die gleiche Anzahl von Dateien entfernen. - Sie benennen eine Datei in
$fpath
um . - Sie fügen den
#compdef
hinzu oder ändern ihn (oder#autoload
) Zeile am Anfang der Datei.
Dieser letzte Punkt neigt dazu, beim Testen zu beißen. Wenn Sie die #compdef
ändern müssen Sie die .zcompdump
entfernen Datei und starten Sie zsh neu (oder führen Sie compinit
erneut aus ).
Wenn Sie Vervollständigungen in ein verteilbares Paket packen, legen Sie die Vervollständigungsdatei einfach in einem Verzeichnis ab, das sich im systemweiten $fpath
befindet . Für ein Ubuntu-Paket ist der geeignete Ort /usr/share/zsh/vendor-completions
. Für etwas, das unter /usr/local
installiert ist , das ist /usr/local/share/zsh/site-functions
. Das ist alles, was Sie tun müssen.
Das einzige, was nicht transparent ist, ist, ob Sie #compdef
ändern müssen bei einem Upgrade oder wenn Sie einige Dateien entfernen oder umbenennen. In solchen Fällen müssen Benutzer ihre Cache-Datei entfernen, und das können Sie nicht mit einem Paket tun, das auf einem Mehrbenutzer-Computer installiert wird.