W zsh ścieżka wyszukiwania funkcji ($ fpath) definiuje zestaw katalogów, które zawierają pliki, które można oznaczyć do automatycznego załadowania, gdy funkcja, którą zawierają, jest potrzebna po raz pierwszy.
Zsh ma dwa tryby automatycznego ładowania plików: rodzimy sposób Zsha i inny tryb podobny do automatycznego ładowania ksh. Ten ostatni jest aktywny, jeśli ustawiona jest opcja KSH_AUTOLOAD. Tryb macierzysty Zsh jest domyślny i nie będę tutaj omawiał innych sposobów (zobacz „man zshmisc” i „man zshoptions”, aby uzyskać szczegółowe informacje na temat automatycznego ładowania w stylu ksh).
W porządku. Załóżmy, że masz katalog `~ / .zfunc 'i chcesz, aby był on częścią ścieżki wyszukiwania funkcji, wykonaj następujące czynności:
fpath=( ~/.zfunc "${fpath[@]}" )
To dodaje twój prywatny katalog na początku ścieżki wyszukiwania. Jest to ważne, jeśli chcesz zastąpić funkcje z instalacji zsh własną (np. Jeśli chcesz użyć zaktualizowanej funkcji uzupełniania, takiej jak `_git 'z repozytorium CVS zsh ze starszą zainstalowaną wersją powłoki).
Warto również zauważyć, że katalogi z `$ fpath 'nie są przeszukiwane rekurencyjnie. Jeśli chcesz, aby twój prywatny katalog był przeszukiwany rekurencyjnie, musisz sam o to zadbać, w ten sposób (poniższy fragment wymaga ustawienia opcji `EXTENDED_GLOB '):
fpath=(
~/.zfuncs
~/.zfuncs/**/*~*/(CVS)#(/N)
"${fpath[@]}"
)
Może to wyglądać tajemniczo dla niewprawnego oka, ale tak naprawdę dodaje wszystkie katalogi poniżej `~ / .zfunc 'do` $ fpath', ignorując katalogi o nazwie „CVS” (co jest przydatne, jeśli planujesz wykupić całość drzewo funkcji z CVS zsh do twojej prywatnej ścieżki wyszukiwania).
Załóżmy, że masz plik `~ / .zfunc / hello ', który zawiera następujący wiersz:
printf 'Hello world.\n'
Wszystko, co musisz teraz zrobić, to zaznaczyć funkcję, która zostanie automatycznie załadowana po pierwszym odwołaniu:
autoload -Uz hello
„O co chodzi -Uz?”, Pytasz? Cóż, to tylko zestaw opcji, które spowodują, że `autoload 'zrobi właściwą rzecz, bez względu na to, jakie opcje są ustawione inaczej. `U 'wyłącza rozszerzenie aliasu podczas ładowania funkcji, a` z' wymusza automatyczne ładowanie w stylu zsh, nawet jeśli `KSH_AUTOLOAD 'jest ustawiony z jakiegokolwiek powodu.
Po zakończeniu tej czynności możesz użyć nowej funkcji hello:
zsh% witam
Witaj świecie.
Słowo o pozyskiwaniu tych plików: to po prostu źle . Jeśli źródłowy plik „~ / .zfunc / hello”, po prostu wydrukuje „Hello world”. pewnego razu. Nic więcej. Żadna funkcja nie zostanie zdefiniowana. Poza tym pomysł polega na ładowaniu kodu funkcji tylko wtedy, gdy jest to wymagane . Po wywołaniu `autoload 'definicja funkcji nie jest czytana. Funkcja jest właśnie oznaczona do automatycznego ładowania później w razie potrzeby.
I wreszcie uwaga na temat $ FPATH i $ fpath: Zsh zachowuje je jako parametry powiązane. Parametr pisany małymi literami to tablica. Wersja z dużymi literami jest skalarnym ciągiem znaków, który zawiera wpisy z połączonej tablicy połączone dwukropkami pomiędzy wpisami. Odbywa się to, ponieważ obsługa listy skalarów jest znacznie bardziej naturalna przy użyciu tablic, przy jednoczesnym zachowaniu kompatybilności wstecznej dla kodu korzystającego z parametru skalarnego. Jeśli wybierzesz opcję $ FPATH (skalarną), musisz zachować ostrożność:
FPATH=~/.zfunc:$FPATH
będzie działać, podczas gdy następujące nie będą:
FPATH="~/.zfunc:$FPATH"
Powodem jest to, że interpretacja tyldy nie jest wykonywana w podwójnych cudzysłowach. Jest to prawdopodobnie źródło twoich problemów. Jeśli echo $FPATH
drukuje tyldę, a nie rozwiniętą ścieżkę, to nie będzie działać. Dla bezpieczeństwa użyłbym $ HOME zamiast tyldy takiej jak ta:
FPATH="$HOME/.zfunc:$FPATH"
To powiedziawszy, wolałbym raczej użyć parametru tablicy, jak na początku tego objaśnienia.
Nie powinieneś również eksportować parametru $ FPATH. Jest potrzebny tylko w bieżącym procesie powłoki, a nie przez żadne z jego potomków.
Aktualizacja
Odnośnie zawartości plików w `$ fpath ':
W przypadku automatycznego ładowania w stylu zsh zawartość pliku stanowi treść zdefiniowanej przez niego funkcji. Zatem plik o nazwie „cześć” zawierający wiersz echo "Hello world."
całkowicie definiuje funkcję o nazwie „cześć”. Możesz
hello () { ... }
ominąć kod, ale byłoby to zbyteczne.
Twierdzenie, że jeden plik może zawierać tylko jedną funkcję, nie jest jednak całkowicie poprawne.
Zwłaszcza jeśli spojrzysz na niektóre funkcje z systemu uzupełniania opartego na funkcjach (compsys), szybko zdasz sobie sprawę, że jest to nieporozumienie. Możesz dowolnie definiować dodatkowe funkcje w pliku funkcji. Możesz także wykonać dowolną inicjalizację, która może być konieczna przy pierwszym wywołaniu funkcji. Jednak gdy to zrobisz, zawsze zdefiniujesz funkcję o nazwie takiej jak plik w pliku i wywołasz tę funkcję na końcu pliku, aby była uruchamiana przy pierwszym wywołaniu funkcji.
Jeśli - z podfunkcjami - nie zdefiniowałeś funkcji o nazwie takiej jak plik w pliku, skończyłbyś z tą funkcją zawierającą definicje funkcji (mianowicie definicje podfunkcji w pliku). Skutecznie definiowałbyś wszystkie swoje podfunkcje przy każdym wywołaniu funkcji o nazwie takiej jak plik. Zwykle nie jest to pożądane, więc ponownie zdefiniujesz funkcję, która nazywa się jak plik w pliku.
Dołączę krótki szkielet, który da ci wyobrażenie o tym, jak to działa:
# 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 "$@"
Gdybyś uruchomił ten głupi przykład, pierwszy przebieg wyglądałby tak:
zsh% witam
inicjowanie ...
Witaj świecie.
Kolejne połączenia będą wyglądać następująco:
zsh% witam
Witaj świecie.
Mam nadzieję, że to wszystko wyjaśni.
(Jednym z bardziej złożonych przykładów, w których wykorzystuje się wszystkie te sztuczki, jest wspomniana już funkcja ` _tmux 'z systemu uzupełniania opartego na funkcji zsh.)