Dans zsh, le chemin de recherche de la fonction ($ fpath) définit un ensemble de répertoires contenant des fichiers pouvant être marqués pour être chargés automatiquement lorsque la fonction qu’ils contiennent est requise pour la première fois.
Zsh a deux modes de chargement automatique des fichiers: le mode natif de Zsh et un autre mode qui ressemble au chargement automatique de ksh. Ce dernier est actif si l'option KSH_AUTOLOAD est définie. Le mode natif de Zsh est le mode par défaut et je ne discuterai pas de l'inverse (voir "man zshmisc" et "man zshoptions" pour plus de détails sur le chargement automatique de style ksh).
D'accord. Supposons que vous ayez un répertoire `~ / .zfunc 'et que vous souhaitiez qu'il fasse partie du chemin de recherche de la fonction, procédez comme suit:
fpath=( ~/.zfunc "${fpath[@]}" )
Cela ajoute votre répertoire privé au début du chemin de recherche. Cela est important si vous souhaitez remplacer les fonctions de l'installation de zsh par les vôtres (par exemple, lorsque vous souhaitez utiliser une fonction de complétion mise à jour telle que `_git 'du référentiel CVS de zsh avec une version plus ancienne du shell).
Il est également intéressant de noter que les répertoires de `$ fpath 'ne sont pas recherchés de manière récursive. Si vous souhaitez que votre répertoire privé fasse l'objet d'une recherche récursive, vous devrez vous en occuper vous-même, comme ceci (le fragment de code suivant nécessite la définition de l'option `EXTENDED_GLOB '):
fpath=(
~/.zfuncs
~/.zfuncs/**/*~*/(CVS)#(/N)
"${fpath[@]}"
)
Cela peut sembler mystérieux à l’œil nu, mais il ajoute en fait tous les répertoires situés sous ~ ~. arborescence des fonctions du CVS de zsh dans votre chemin de recherche privé).
Supposons que vous ayez un fichier `~ / .zfunc / hello 'contenant la ligne suivante:
printf 'Hello world.\n'
Il ne vous reste plus qu'à marquer la fonction à charger automatiquement dès sa première référence:
autoload -Uz hello
"De quoi parle le -Uz?", Vous demandez? Eh bien, c’est juste un ensemble d’options qui feront que le «chargement automatique» fera le bon choix, quelles que soient les options définies. Le «U» désactive le développement des alias pendant le chargement de la fonction et le «z» force le chargement automatique dans le style zsh même si «KSH_AUTOLOAD» est défini pour une raison quelconque.
Une fois cela fait, vous pouvez utiliser votre nouvelle fonction `hello ':
zsh% bonjour
Bonjour le monde.
Un mot sur la recherche de ces fichiers: c’est faux . Si vous aviez source ce fichier `~ / .zfunc / hello ', il n’aurait qu’imprimer" Hello world ". une fois que. Rien de plus. Aucune fonction ne sera définie. De plus, l’idée est de ne charger le code de la fonction que lorsque cela est nécessaire . Après l'appel `autoload ', la définition de la fonction n'est pas lue. La fonction est juste marquée pour être auto-chargée plus tard si nécessaire.
Et enfin, une note sur $ FPATH et $ fpath: Zsh les maintient en tant que paramètres liés. Le paramètre minuscule est un tableau. La version majuscule est une chaîne scalaire, qui contient les entrées du tableau lié joint par des points entre deux entrées. Ceci est fait car la gestion d'une liste de scalaires est beaucoup plus naturelle à l'aide de tableaux, tout en maintenant la compatibilité avec les versions antérieures pour le code qui utilise le paramètre scalar. Si vous choisissez d'utiliser $ FPATH (le scalaire), vous devez faire attention:
FPATH=~/.zfunc:$FPATH
fonctionnera, tandis que ce qui suit ne fonctionnera pas:
FPATH="~/.zfunc:$FPATH"
La raison en est que le développement de tilde n’est pas effectué entre guillemets doubles. C'est probablement la source de vos problèmes. Si echo $FPATH
imprime un tilde et non un chemin développé, cela ne fonctionnera pas. Pour être sûr, j'utiliserais $ HOME au lieu d'un tilde comme celui-ci:
FPATH="$HOME/.zfunc:$FPATH"
Cela dit, je préférerais de beaucoup utiliser le paramètre array comme je l’ai fait en haut de cette explication.
Vous ne devriez pas non plus exporter le paramètre $ FPATH. Il n’est nécessaire que par le processus shell actuel et non par l’un de ses enfants.
Mise à jour
En ce qui concerne le contenu des fichiers dans `$ fpath ':
Avec le chargement automatique de style zsh, le contenu d'un fichier est le corps de la fonction qu'il définit. Ainsi, un fichier nommé "hello" contenant une ligne echo "Hello world."
définit complètement une fonction appelée "hello". Vous êtes libre de
hello () { ... }
contourner le code, mais ce serait superflu.
L'affirmation selon laquelle un fichier ne peut contenir qu'une seule fonction n'est cependant pas tout à fait correcte.
Surtout si vous regardez certaines fonctions du système de complétion basé sur les fonctions (compsys), vous vous rendrez vite compte qu'il s'agit d'une idée fausse. Vous êtes libre de définir des fonctions supplémentaires dans un fichier de fonctions. Vous êtes également libre de faire toute sorte d’initialisation que vous devrez peut-être faire lors du premier appel de la fonction. Cependant, lorsque vous le ferez, vous définissez toujours une fonction nommée comme le fichier dans le fichier et appelez cette fonction à la fin du fichier pour qu'il soit exécuté la première fois que la fonction est référencée.
Si - avec les sous-fonctions - vous ne définissez pas une fonction nommée comme le fichier dans le fichier, vous obtiendrez des définitions de fonctions contenant cette fonction (à savoir celles des sous-fonctions du fichier). Vous définiriez effectivement toutes vos sous-fonctions chaque fois que vous appelez la fonction nommée comme le fichier. Normalement, ce n'est pas ce que vous voulez, vous redéfinissez donc une fonction nommée comme le fichier dans le fichier.
Je vais inclure un court squelette, qui vous donnera une idée de la façon dont cela fonctionne:
# 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 "$@"
Si vous utilisiez cet exemple stupide, la première exécution ressemblerait à ceci:
zsh% bonjour
initialisation ...
Bonjour le monde.
Et les appels consécutifs ressembleront à ceci:
zsh% bonjour
Bonjour le monde.
J'espère que cela clarifie les choses.
(L'un des exemples les plus complexes du monde réel qui utilise toutes ces astuces est la fonction ` _tmux ' déjà mentionnée du système d'achèvement basé sur la fonction de zsh.)