En zsh, la ruta de búsqueda de funciones ($ fpath) define un conjunto de directorios que contienen archivos que se pueden marcar para cargarse automáticamente cuando se necesita por primera vez la función que contienen.
Zsh tiene dos modos de carga automática de archivos: la forma nativa de Zsh y otro modo que se asemeja a la carga automática de ksh. Este último está activo si se establece la opción KSH_AUTOLOAD. El modo nativo de Zsh es el predeterminado y no hablaré de la otra manera aquí (consulte "man zshmisc" y "man zshoptions" para obtener detalles sobre la carga automática de estilo ksh).
Bueno. Supongamos que tiene un directorio `~ / .zfunc 'y desea que forme parte de la ruta de búsqueda de funciones, haga esto:
fpath=( ~/.zfunc "${fpath[@]}" )
Eso agrega su directorio privado al frente de la ruta de búsqueda. Eso es importante si desea anular las funciones de la instalación de zsh con las suyas propias (por ejemplo, cuando desea utilizar una función de finalización actualizada como `_git 'del repositorio CVS de zsh con una versión instalada más antigua del shell).
También vale la pena señalar que los directorios de `$ fpath 'no se buscan de forma recursiva. Si desea que su directorio privado se busque de forma recursiva, tendrá que ocuparse de eso usted mismo, de esta manera (el siguiente fragmento requiere que se configure la opción `EXTENDED_GLOB '):
fpath=(
~/.zfuncs
~/.zfuncs/**/*~*/(CVS)#(/N)
"${fpath[@]}"
)
Puede parecer críptico para el ojo inexperto, pero realmente solo agrega todos los directorios debajo de '~ / .zfunc' a '$ fpath', mientras ignora los directorios llamados "CVS" (lo cual es útil, si está planeando pagar un todo árbol de funciones del CVS de zsh en su ruta de búsqueda privada).
Supongamos que tiene un archivo `~ / .zfunc / hello 'que contiene la siguiente línea:
printf 'Hello world.\n'
Todo lo que necesita hacer ahora es marcar la función que se cargará automáticamente en su primera referencia:
autoload -Uz hello
"¿De qué se trata el -Uz?" Bueno, eso es solo un conjunto de opciones que harán que la 'carga automática' haga lo correcto, sin importar qué opciones se establezcan de lo contrario. La 'U' deshabilita la expansión de alias mientras se carga la función y la 'z' fuerza la carga automática de estilo zsh incluso si 'KSH_AUTOLOAD' está configurado por cualquier razón.
Después de que se haya resuelto, puede usar su nueva función 'hola':
zsh% hola
Hola Mundo.
Una palabra sobre el abastecimiento de estos archivos: eso está mal . Si obtiene ese archivo `~ / .zfunc / hello ', simplemente imprimirá" Hola mundo ". una vez. Nada mas. No se definirá ninguna función. Y además, la idea es cargar solo el código de la función cuando sea necesario . Después de la llamada de 'carga automática', la definición de la función no se lee. La función se marca para cargarse automáticamente más tarde según sea necesario.
Y finalmente, una nota sobre $ FPATH y $ fpath: Zsh los mantiene como parámetros vinculados. El parámetro en minúscula es una matriz. La versión en mayúsculas es un escalar de cadena, que contiene las entradas de la matriz vinculada unida por dos puntos entre las entradas. Esto se hace, porque manejar una lista de escalares es mucho más natural usando matrices, al tiempo que se mantiene la compatibilidad con versiones anteriores para el código que usa el parámetro escalar. Si elige usar $ FPATH (el escalar), debe tener cuidado:
FPATH=~/.zfunc:$FPATH
funcionará, mientras que lo siguiente no funcionará:
FPATH="~/.zfunc:$FPATH"
La razón es que la expansión de tilde no se realiza entre comillas dobles. Esta es probablemente la fuente de tus problemas. Si echo $FPATH
imprime una tilde y no una ruta expandida, entonces no funcionará. Para estar seguro, usaría $ HOME en lugar de una tilde como esta:
FPATH="$HOME/.zfunc:$FPATH"
Dicho esto, preferiría usar el parámetro de matriz como lo hice al principio de esta explicación.
Tampoco debe exportar el parámetro $ FPATH. Solo es necesario para el proceso de shell actual y no para ninguno de sus hijos.
Actualizar
Con respecto al contenido de los archivos en `$ fpath ':
Con la carga automática de estilo zsh, el contenido de un archivo es el cuerpo de la función que define. Así, un archivo llamado "hola" que contiene una línea echo "Hello world."
define completamente una función llamada "hola". Eres libre de poner
hello () { ... }
el código, pero eso sería superfluo.
Sin embargo, la afirmación de que un archivo solo puede contener una función no es del todo correcta.
Especialmente si observa algunas funciones del sistema de finalización basado en funciones (compsys), se dará cuenta rápidamente de que es un error. Usted es libre de definir funciones adicionales en un archivo de funciones. También es libre de hacer cualquier tipo de inicialización, que puede necesitar hacer la primera vez que se llama a la función. Sin embargo, cuando lo haga, siempre definirá una función que se denomina como el archivo en el archivo y llamará a esa función al final del archivo, por lo que se ejecuta la primera vez que se hace referencia a la función.
Si, con las subfunciones, no definió una función denominada como el archivo dentro del archivo, terminaría con esa función con definiciones de función (es decir, las de las subfunciones en el archivo). Definiría efectivamente todas sus subfunciones cada vez que llame a la función que se nombra como el archivo. Normalmente, eso no es lo que desea, por lo que redefiniría una función, que se llama como el archivo dentro del archivo.
Incluiré un esqueleto corto, que te dará una idea de cómo funciona:
# 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 ejecutara este ejemplo tonto, la primera ejecución se vería así:
zsh% hola
inicializando ...
Hola Mundo.
Y las llamadas consecutivas se verán así:
zsh% hola
Hola Mundo.
Espero que esto aclare las cosas.
(Uno de los ejemplos más complejos del mundo real que usa todos esos trucos es la función ` _tmux ' ya mencionada del sistema de finalización basado en funciones de zsh).