In zsh, il percorso di ricerca della funzione ($ fpath) definisce una serie di directory, che contengono file che possono essere contrassegnati per essere caricati automaticamente quando la funzione in essi contenuta è necessaria per la prima volta.
Zsh ha due modalità di caricamento automatico dei file: la modalità nativa di Zsh e un'altra modalità che ricorda il caricamento automatico di ksh. Quest'ultimo è attivo se è impostata l'opzione KSH_AUTOLOAD. La modalità nativa di Zsh è quella predefinita e non discuterò qui in altro modo (vedi "man zshmisc" e "man zshoptions" per i dettagli sul caricamento automatico in stile ksh).
Va bene. Supponiamo che tu abbia una directory `~ / .zfunc 'e desideri che faccia parte del percorso di ricerca della funzione, fai questo:
fpath=( ~/.zfunc "${fpath[@]}" )
Che aggiunge la directory privato al fronte del percorso di ricerca. Ciò è importante se si desidera sovrascrivere le funzioni dall'installazione di zsh con le proprie (come, quando si desidera utilizzare una funzione di completamento aggiornata come `_git 'dal repository CVS di zsh con una versione installata precedente della shell).
Vale anche la pena notare che le directory di "$ fpath" non vengono cercate in modo ricorsivo. Se desideri che la tua directory privata venga cercata in modo ricorsivo, dovrai occupartene da solo, in questo modo (il frammento seguente richiede che l'opzione `EXTENDED_GLOB 'sia impostata):
fpath=(
~/.zfuncs
~/.zfuncs/**/*~*/(CVS)#(/N)
"${fpath[@]}"
)
Può sembrare criptico a occhio nudo, ma in realtà aggiunge tutte le directory sotto `~ / .zfunc 'a` $ fpath', ignorando le directory chiamate "CVS" (che è utile, se hai intenzione di fare il checkout di un intero albero delle funzioni dal CVS di zsh nel percorso di ricerca privato).
Supponiamo che tu abbia un file `~ / .zfunc / hello 'che contiene la seguente riga:
printf 'Hello world.\n'
Tutto ciò che devi fare ora è contrassegnare la funzione da caricare automaticamente al suo primo riferimento:
autoload -Uz hello
"Di cosa parla -Uz?", Chiedi? Bene, questa è solo una serie di opzioni che fanno sì che `autoload 'faccia la cosa giusta, indipendentemente da quali opzioni vengano impostate diversamente. La `U 'disabilita l'espansione dell'alias mentre la funzione viene caricata e la' z 'forza il caricamento automatico in stile zsh anche se` KSH_AUTOLOAD' è impostato per qualsiasi motivo.
Dopo che è stato curato, puoi usare la tua nuova funzione "ciao":
ciao zsh%
Ciao mondo.
Una parola sull'approvvigionamento di questi file: è sbagliato . Se si procurasse quel file `~ / .zfunc / hello ', si stampa semplicemente" Ciao mondo ". una volta. Niente di più. Nessuna funzione sarà definita. Inoltre, l'idea è di caricare il codice della funzione solo quando è necessario . Dopo la chiamata di `autoload 'la definizione della funzione non viene letta. La funzione è appena contrassegnata per essere caricata automaticamente in seguito, se necessario.
E infine, una nota su $ FPATH e $ fpath: Zsh mantiene quelli come parametri collegati. Il parametro minuscolo è un array. La versione maiuscola è una stringa scalare, che contiene le voci dell'array collegato unite da due punti tra le voci. Questo viene fatto, poiché la gestione di un elenco di scalari è molto più naturale utilizzando le matrici, pur mantenendo la compatibilità con le versioni precedenti per il codice che utilizza il parametro scalare. Se scegli di utilizzare $ FPATH (quello scalare), devi fare attenzione:
FPATH=~/.zfunc:$FPATH
funzionerà, mentre i seguenti non:
FPATH="~/.zfunc:$FPATH"
Il motivo è che l'espansione della tilde non viene eseguita tra virgolette doppie. Questa è probabilmente la fonte dei tuoi problemi. Se echo $FPATH
stampa una tilde e non un percorso espanso, non funzionerà. Per sicurezza, userei $ HOME invece di una tilde come questa:
FPATH="$HOME/.zfunc:$FPATH"
Detto questo, preferirei di gran lunga utilizzare il parametro array come ho fatto all'inizio di questa spiegazione.
Inoltre, non dovresti esportare il parametro $ FPATH. È necessario solo per l'attuale processo di shell e non per nessuno dei suoi figli.
Aggiornare
Per quanto riguarda il contenuto dei file in `$ fpath ':
Con il caricamento automatico in stile zsh, il contenuto di un file è il corpo della funzione che definisce. Quindi un file chiamato "ciao" contenente una riga echo "Hello world."
definisce completamente una funzione chiamata "ciao". Sei libero di inserire
hello () { ... }
il codice, ma sarebbe superfluo.
Tuttavia, l'affermazione secondo cui un file può contenere solo una funzione non è del tutto corretta.
Soprattutto se guardi alcune funzioni dal sistema di completamento basato sulle funzioni (compsys) ti renderai presto conto che si tratta di un malinteso. Sei libero di definire funzioni aggiuntive in un file di funzioni. Sei anche libero di eseguire qualsiasi tipo di inizializzazione, che potrebbe essere necessario eseguire la prima volta che viene chiamata la funzione. Tuttavia, quando lo fai definirai sempre una funzione che è denominata come il file nel file e la chiamerai alla fine del file, in modo che venga eseguita la prima volta che viene fatto riferimento alla funzione.
Se - con le sotto-funzioni - non hai definito una funzione chiamata come il file all'interno del file, finiresti con quella funzione che contiene definizioni di funzioni (cioè quelle delle sotto-funzioni nel file). Definiresti effettivamente tutte le tue sotto-funzioni ogni volta che chiami la funzione che è chiamata come il file. Normalmente, non è quello che vuoi, quindi potresti ridefinire una funzione, che ha il nome del file all'interno del file.
Includerò uno scheletro corto, che ti darà un'idea di come funziona:
# Let's again assume that these are the contents of a file called "hello".
# You may run arbitrary code in here, that will run the first time the
# function is referenced. Commonly, that is initialisation code. For example
# the `_tmux' completion function does exactly that.
echo initialising...
# You may also define additional functions in here. Note, that these
# functions are visible in global scope, so it is paramount to take
# care when you're naming these so you do not shadow existing commands or
# redefine existing functions.
hello_helper_one () {
printf 'Hello'
}
hello_helper_two () {
printf 'world.'
}
# Now you should redefine the "hello" function (which currently contains
# all the code from the file) to something that covers its actual
# functionality. After that, the two helper functions along with the core
# function will be defined and visible in global scope.
hello () {
printf '%s %s\n' "$(hello_helper_one)" "$(hello_helper_two)"
}
# Finally run the redefined function with the same arguments as the current
# run. If this is left out, the functionality implemented by the newly
# defined "hello" function is not executed upon its first call. So:
hello "$@"
Se avessi eseguito questo esempio sciocco, la prima corsa sarebbe simile a questa:
ciao zsh%
inizializzazione ...
Ciao mondo.
E le chiamate consecutive appariranno così:
ciao zsh%
Ciao mondo.
Spero che questo chiarisca le cose.
(Uno degli esempi più complessi del mondo reale che utilizza tutti questi trucchi è la già citata funzione ` _tmux 'dal sistema di completamento basato sulle funzioni di zsh.)