Es fällt mir schwer, meine eigenen Shell-Funktionen in zsh zu definieren und auszuführen. Ich befolgte die Anweisungen in der offiziellen Dokumentation und versuchte es zunächst mit einem einfachen Beispiel, brachte es aber nicht zum Laufen.
Ich habe einen Ordner:
~/.my_zsh_functions
In diesem Ordner habe ich eine Datei functions_1
mit rwx
Benutzerberechtigungen aufgerufen . In dieser Datei habe ich folgende Shell-Funktion definiert:
my_function () {
echo "Hello world";
}
Ich definierte FPATH
, um den Pfad zum Ordner einzuschließen ~/.my_zsh_functions
:
export FPATH=~/.my_zsh_functions:$FPATH
Ich kann .my_zsh_functions
mit echo $FPATH
oder bestätigen, dass sich der Ordner im Funktionspfad befindetecho $fpath
Wenn ich dann aber folgendes aus der Shell probiere:
> autoload my_function
> my_function
Ich bekomme:
zsh: my_test_function: Funktionsdefinitionsdatei nicht gefunden
Muss ich noch etwas tun, um anrufen zu können my_function
?
Aktualisieren:
Die bisherigen Antworten legen nahe, die Datei mit den zsh-Funktionen zu beschaffen. Das macht Sinn, aber ich bin ein bisschen verwirrt. Sollte zsh nicht wissen, wo sich diese Dateien befinden FPATH
? Was ist der Zweck von autoload
dann?
quelle
Antworten:
In zsh definiert der Funktionssuchpfad ($ fpath) eine Reihe von Verzeichnissen, die Dateien enthalten, die zum automatischen Laden markiert werden können, wenn die darin enthaltene Funktion zum ersten Mal benötigt wird.
Zsh bietet zwei Modi zum automatischen Laden von Dateien: den systemeigenen Modus von Zsh und einen anderen Modus, der dem automatischen Laden von ksh ähnelt. Letzteres ist aktiv, wenn die Option KSH_AUTOLOAD gesetzt ist. Der native Modus von Zsh ist die Standardeinstellung, und ich werde hier nicht auf die andere Weise eingehen (siehe "man zshmisc" und "man zshoptions" für Details zum automatischen Laden im ksh-Stil).
Okay. Angenommen, Sie haben ein Verzeichnis "~ / .zfunc" und möchten, dass es Teil des Funktionssuchpfads ist. Gehen Sie dazu folgendermaßen vor:
Das fügt Ihr privates Verzeichnis an der Spitze des Suchpfads hinzu. Dies ist wichtig, wenn Sie Funktionen aus der Installation von zsh mit Ihren eigenen überschreiben möchten (z. B. wenn Sie eine aktualisierte Vervollständigungsfunktion wie _git aus dem CVS-Repository von zsh mit einer älteren installierten Version der Shell verwenden möchten).
Es ist auch erwähnenswert, dass die Verzeichnisse von $ fpath nicht rekursiv durchsucht werden. Wenn Sie möchten, dass Ihr privates Verzeichnis rekursiv durchsucht wird, müssen Sie sich selbst darum kümmern (für das folgende Snippet muss die Option EXTENDED_GLOB gesetzt sein):
Es sieht für das ungeübte Auge vielleicht kryptisch aus, fügt aber wirklich nur alle Verzeichnisse unterhalb von ~ / .zfunc zu $ fpath hinzu, während Verzeichnisse mit dem Namen "CVS" ignoriert werden (was nützlich ist, wenn Sie vorhaben, ein Ganzes auszuchecken Funktionsbaum aus dem CVS von zsh in Ihren privaten Suchpfad).
Nehmen wir an, Sie haben eine Datei "~ / .zfunc / hello", die die folgende Zeile enthält:
Alles, was Sie jetzt tun müssen, ist , die Funktion zu markieren, die bei ihrer ersten Referenz automatisch geladen werden soll:
"Worum geht es in der -Uz?", Fragst du? Nun, das ist nur eine Reihe von Optionen, die dazu führen, dass "Autoload" das Richtige tut, unabhängig davon, welche Optionen ansonsten eingestellt werden. Das "U" deaktiviert die Alias-Erweiterung, während die Funktion geladen wird, und das "z" erzwingt das automatische Laden im Stil von "zsh", auch wenn "KSH_AUTOLOAD" aus irgendeinem Grund festgelegt ist.
Nachdem dies erledigt wurde, können Sie Ihre neue "Hallo" -Funktion verwenden:
Ein Wort zur Beschaffung dieser Dateien: Das ist einfach falsch . Wenn Sie diese `~ / .zfunc / hello'-Datei als Quelle verwenden, wird nur" Hallo Welt "gedruckt. Einmal. Nichts mehr. Es wird keine Funktion definiert. Außerdem besteht die Idee darin, den Funktionscode nur dann zu laden, wenn er benötigt wird . Nach dem Aufruf von `autoload 'wird die Definition der Funktion nicht gelesen. Die Funktion ist nur markiert, um später bei Bedarf automatisch geladen zu werden.
Zum Schluss noch ein Hinweis zu $ FPATH und $ fpath: Zsh behält diese als verknüpfte Parameter bei. Der Parameter in Kleinbuchstaben ist ein Array. Die Großbuchstabenversion ist ein String-Skalar, der die Einträge aus dem verknüpften Array enthält, die durch Doppelpunkte zwischen den Einträgen verbunden sind. Dies geschieht, weil der Umgang mit einer Liste von Skalaren mit Arrays viel natürlicher ist und gleichzeitig die Abwärtskompatibilität für Code aufrechterhalten wird, der den Parameter scalar verwendet. Wenn Sie sich für die Verwendung von $ FPATH (dem skalaren) entscheiden, müssen Sie vorsichtig sein:
wird funktionieren, während die folgenden nicht:
Der Grund dafür ist, dass die Tilde-Erweiterung nicht in doppelten Anführungszeichen erfolgt. Dies ist wahrscheinlich die Ursache Ihrer Probleme. Wenn
echo $FPATH
eine Tilde und kein erweiterter Pfad gedruckt wird, funktioniert dies nicht. Aus Sicherheitsgründen würde ich $ HOME anstelle einer Tilde wie folgt verwenden:Davon abgesehen würde ich den Array-Parameter viel lieber verwenden, wie ich es oben in dieser Erklärung getan habe.
Sie sollten den Parameter $ FPATH auch nicht exportieren. Es wird nur vom aktuellen Shell-Prozess und nicht von einem seiner untergeordneten Elemente benötigt.
Aktualisieren
Bezüglich des Inhalts von Dateien in "$ fpath":
Beim automatischen Laden im Stil von zsh ist der Inhalt einer Datei der Hauptteil der von ihr definierten Funktion. Somit definiert eine Datei mit dem Namen "hallo", die eine Zeile enthält,
echo "Hello world."
vollständig eine Funktion mit dem Namen "hallo". Es steht Ihnen frei,hello () { ... }
den Code zu umgehen, aber das wäre überflüssig.Die Behauptung, dass eine Datei nur eine Funktion enthalten darf, ist jedoch nicht ganz richtig.
Insbesondere wenn Sie sich einige Funktionen des funktionsbasierten Vervollständigungssystems (compsys) ansehen, werden Sie schnell feststellen, dass dies ein Missverständnis ist. Sie können zusätzliche Funktionen in einer Funktionsdatei definieren. Sie können auch jede Art von Initialisierung durchführen, die Sie möglicherweise beim ersten Aufruf der Funktion durchführen müssen. Wenn Sie dies jedoch tun, definieren Sie immer eine Funktion, die wie die Datei in der Datei benannt ist, und rufen diese Funktion am Ende der Datei auf, damit sie beim ersten Aufrufen der Funktion ausgeführt wird.
Wenn Sie bei Unterfunktionen keine Funktion definiert haben, die wie die Datei in der Datei benannt ist, enthält diese Funktion Funktionsdefinitionen (dh die Unterfunktionen in der Datei). Sie würden effektiv alle Ihre Unterfunktionen jedes Mal definieren, wenn Sie die Funktion aufrufen, die wie die Datei benannt ist. Normalerweise ist das nicht das, was Sie wollen, also würden Sie eine Funktion neu definieren, die wie die Datei in der Datei benannt ist.
Ich werde ein kurzes Skelett beifügen, das Ihnen eine Vorstellung davon gibt, wie das funktioniert:
Wenn Sie dieses alberne Beispiel ausführen würden, würde der erste Lauf folgendermaßen aussehen:
Aufeinanderfolgende Anrufe sehen dann so aus:
Ich hoffe das klärt die Dinge auf.
(Eines der komplexeren realen Beispiele, das all diese Tricks verwendet, ist die bereits erwähnte Funktion " _tmux " aus dem funktionsbasierten Vervollständigungssystem von zsh.)
quelle
my_function () { }
in IhremHello world
Beispiel nicht die Syntax verwendet haben . Wenn die Syntax nicht benötigt wird, wann ist sie sinnvoll?Der Name der Datei in einem Verzeichnis, das von einem
fpath
Element benannt wird , muss mit dem Namen der von ihm definierten automatisch ladbaren Funktion übereinstimmen.Ihre Funktion heißt
my_function
und~/.my_zsh_functions
ist das beabsichtigte Verzeichnis in Ihrerfpath
, daher sollte die Definition vonmy_function
in der Datei sein~/.my_zsh_functions/my_function
.Der Plural in Ihrem vorgeschlagenen Dateinamen (
functions_1
) zeigt an, dass Sie mehrere Funktionen in die Datei einfügen wollten. Dies ist nicht wiefpath
und Autoloading funktioniert. Sie sollten eine Funktionsdefinition pro Datei haben.quelle
Geben Sie
source ~/.my_zsh_functions/functions1
das Terminal ein und bewerten Siemy_function
, jetzt können Sie die Funktion aufrufenquelle
FPATH
undautoload
dann? Warum muss ich die Datei auch als Quelle angeben? Siehe meine aktualisierte Frage.Sie können eine Datei mit all Ihren Funktionen in Ihrem $ ZDOTDIR / .zshrc wie folgt "laden":
Oder kann einen Punkt "." anstelle von "Quelle".
quelle
FPATH
undautoload
dann? Warum muss ich die Datei auch als Quelle angeben? Siehe meine aktualisierte Frage.Sourcing ist definitiv nicht der richtige Ansatz, da Sie scheinbar nur faule, initialisierte Funktionen benötigen. Dafür
autoload
ist es da. So erreichen Sie, wonach Sie suchen.In Ihrem
~/.my_zsh_functions
, Sie sagen , Sie eine Funktion namens setzen wollen ,my_function
dass echos „Hallo Welt“. Aber Sie binden es in einen Funktionsaufruf ein, und so funktioniert das nicht. Stattdessen müssen Sie eine Datei namens erstellen~/.my_zsh_functions/my_function
. Einfach einfügenecho "Hello world"
, nicht in einen Funktionswrapper. Sie können auch so etwas tun, wenn Sie den Wrapper wirklich bevorzugen.Fügen Sie als Nächstes in Ihrer
.zshrc
Datei Folgendes hinzu:Wenn Sie eine neue ZSH-Shell laden, geben Sie Folgendes ein
which my_function
. Das solltest du sehen:ZSH hat gerade meine_Funktion für Sie gestoppt
autoload -X
. Jetzt rennmy_function
doch einfach nur tippenmy_function
. Sie sollten denHello world
Ausdruck sehen, und jetzt, wenn Sie ausführenwhich my_function
, sollten Sie die Funktion so ausgefüllt sehen:Jetzt kommt die wahre Magie, wenn Sie Ihren gesamten
~/.my_zsh_functions
Ordner für die Arbeit einrichtenautoload
. Wenn Sie möchten, dass jede Datei, die Sie in diesem Ordner ablegen, so funktioniert, ändern Sie das, was Sie in Ihrem Ordner ablegen, in Folgendes.zshrc
:quelle