J'ai du mal à définir et à exécuter mes propres fonctions de shell dans zsh. J'ai suivi les instructions de la documentation officielle et essayé d'abord avec un exemple simple, mais je n'ai pas réussi à le faire fonctionner.
J'ai un dossier:
~/.my_zsh_functions
Dans ce dossier, j'ai un fichier appelé functions_1
avec rwx
des autorisations utilisateur. Dans ce fichier, j'ai défini la fonction shell suivante:
my_function () {
echo "Hello world";
}
J'ai défini FPATH
d'inclure le chemin d'accès au dossier ~/.my_zsh_functions
:
export FPATH=~/.my_zsh_functions:$FPATH
Je peux confirmer que le dossier .my_zsh_functions
est dans le chemin des fonctions avec echo $FPATH
ouecho $fpath
Cependant, si j’essaie ensuite ce qui suit à partir du shell:
> autoload my_function
> my_function
Je reçois:
zsh: my_test_function: fichier de définition de fonction introuvable
Dois-je faire autre chose pour pouvoir appeler my_function
?
Mise à jour:
Les réponses suggèrent jusqu'ici de rechercher le fichier avec les fonctions zsh. Cela a du sens, mais je suis un peu confus. Zsh ne devrait-il pas savoir où se trouvent ces fichiers FPATH
? Quel est le but autoload
alors?
la source
Réponses:
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:
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 '):
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:
Il ne vous reste plus qu'à marquer la fonction à charger automatiquement dès sa première référence:
"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 ':
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:
fonctionnera, tandis que ce qui suit ne fonctionnera pas:
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: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 dehello () { ... }
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:
Si vous utilisiez cet exemple stupide, la première exécution ressemblerait à ceci:
Et les appels consécutifs ressembleront à ceci:
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.)
la source
my_function () { }
dans votreHello world
exemple. Si la syntaxe n'est pas nécessaire, quand serait-il utile de l'utiliser?Le nom du fichier dans un répertoire nommé par un
fpath
élément doit correspondre au nom de la fonction autochargeable qu’il définit.Votre fonction est nommée
my_function
et~/.my_zsh_functions
correspond au répertoire prévu dans votrefpath
; la définition demy_function
devrait donc figurer dans le fichier~/.my_zsh_functions/my_function
.Le pluriel dans votre nom de fichier proposé (
functions_1
) indique que vous aviez l'intention de placer plusieurs fonctions dans le fichier. Ce n'est pas comme çafpath
et le chargement automatique fonctionne. Vous devriez avoir une définition de fonction par fichier.la source
donner
source ~/.my_zsh_functions/functions1
dans le terminal et évaluermy_function
, maintenant vous pourrez appeler la fonctionla source
FPATH
etautoload
ensuite? Pourquoi ai-je également besoin de source le fichier? Voir ma question mise à jour.Vous pouvez "charger" un fichier avec toutes vos fonctions dans votre $ ZDOTDIR / .zshrc comme ceci:
Ou peut utiliser un point "." au lieu de "source".
la source
FPATH
etautoload
ensuite? Pourquoi ai-je également besoin de source le fichier? Voir ma question mise à jour.L’approvisionnement n’est certainement pas la bonne approche, car ce que vous semblez vouloir, c’est avoir des fonctions initialisées paresseuses. C'est pour ça
autoload
. Voici comment vous accomplissez ce que vous recherchez.Dans votre
~/.my_zsh_functions
, vous dites que vous voulez mettre une fonction appeléemy_function
echos "hello world". Mais vous l'enroulez dans un appel de fonction, ce qui n'est pas le cas. Au lieu de cela, vous devez créer un fichier appelé~/.my_zsh_functions/my_function
. Dans ce document, mettez simplementecho "Hello world"
, pas dans un wrapper de fonction. Vous pouvez également faire quelque chose comme ceci si vous préférez vraiment avoir le wrapper.Ensuite, dans votre
.zshrc
fichier, ajoutez ce qui suit:Lorsque vous chargez un nouveau shell ZSH, tapez
which my_function
. Vous devriez voir ceci:ZSH vient d'écraser ma_fonction pour vous
autoload -X
. Maintenant, lancez-vousmy_function
mais tapez justemy_function
. Vous devriez voirHello world
imprimer, et maintenant quand vous courez,which my_function
vous devriez voir la fonction remplie comme ceci:Maintenant, la vraie magie vient lorsque vous configurez votre
~/.my_zsh_functions
dossier entier pour travailler avecautoload
. Si vous voulez que tous les fichiers que vous déposez dans ce dossier fonctionnent comme ceci, changez ce que vous mettez dans votre.zshrc
en quelque chose comme ceci:la source