Как определить и загрузить свою собственную функцию оболочки в zsh

Мне сложно определить и запустить собственные функции оболочки в zsh. Я следил за инструкциями по официальной документации и сначала попробовал легкий пример, но мне не удалось заставить его работать.

У меня есть папка:

~/.my_zsh_functions 

В этой папке у меня есть файл с именем functions_1 с правами пользователя rwx . В этом файле у меня есть следующая функция оболочки:

 my_function () { echo "Hello world"; } 

Я определил FPATH чтобы включить путь к папке ~/.my_zsh_functions :

 export FPATH=~/.my_zsh_functions:$FPATH 

Я могу подтвердить, что папка .my_zsh_functions находится в пути функций с echo $FPATH или echo $fpath

Однако, если я затем попробую следующее из оболочки:

 > autoload my_function > my_function 

Я получил:

zsh: my_test_function: файл определения функции не найден

Есть ли что-то еще, что мне нужно, чтобы иметь возможность вызвать my_function ?

Обновить:

Ответы до сих пор предлагают найти файл с функциями zsh. Это имеет смысл, но я немного смущен. Должно ли zsh знать, где находятся эти файлы с FPATH ? Какова цель autoload ?

4 Solutions collect form web for “Как определить и загрузить свою собственную функцию оболочки в zsh”

В zsh путь поиска функции ($ fpath) определяет набор каталогов, которые содержат файлы, которые могут быть помечены для автоматической загрузки, когда требуемая функция требуется в первый раз.

Zsh имеет два режима автозагрузки файлов: собственный путь Zsh и другой режим, который похож на автозагрузку ksh. Последний активен, если задана опция KSH_AUTOLOAD. Основной режим Zsh – это по умолчанию, и я не буду обсуждать здесь другой путь (см. «Man zshmisc» и «man zshoptions» для получения подробной информации об автозагрузке в стиле ksh).

Хорошо. Скажем, у вас есть каталог `~ / .zfunc ', и вы хотите, чтобы он был частью пути поиска функции, вы делаете это:

 fpath=( ~/.zfunc "${fpath[@]}" ) 

Это добавляет ваш частный каталог в начало пути поиска. Это важно, если вы хотите переопределить функции из установки zsh своими собственными (например, если вы хотите использовать обновленную функцию завершения, такую ​​как `_git 'из репозитория CVS от zsh, с более старой установленной версией оболочки).

Также стоит отметить, что каталоги из `$ fpath 'не ищут рекурсивно. Если вы хотите, чтобы ваш личный каталог искался рекурсивно, вам придется позаботиться об этом самостоятельно (например, следующий фрагмент требует установки опции EXTENDED_GLOB):

 fpath=( ~/.zfuncs ~/.zfuncs/**/*~*/(CVS)#(/N) "${fpath[@]}" ) 

Он может выглядеть загадочным для неподготовленного глаза, но на самом деле он просто добавляет все каталоги ниже `~ / .zfunc 'в` $ fpath', игнорируя каталоги, называемые «CVS» (что полезно, если вы планируете проверять целое дерево функций из CVS zsh в ваш личный путь поиска).

Предположим, у вас есть файл `~ / .zfunc / hello ', который содержит следующую строку:

 printf 'Hello world.\n' 

Все, что вам нужно сделать, это отметить, что функция автоматически загружается по первой ссылке:

 autoload -Uz hello 

«Что такое -Уз?», Спросите вы? Ну, это всего лишь набор параметров, которые заставят `autoload 'делать правильные вещи, независимо от того, какие опции устанавливаются иначе. «U» отключает расширение псевдонима во время загрузки функции, а «z» заставляет загружать zsh-стиль, даже если «KSH_AUTOLOAD» установлен по любой причине.

После этого вы можете использовать свою новую функцию hello:

  zsh% hello
 Привет мир. 

Слово о поиске этих файлов: Это просто неправильно . Если вы будете использовать этот файл `~ / .zfunc / hello ', он просто напечатает« Hello world ». один раз. Больше ничего. Функция не будет определена. И, кроме того, идея состоит в том, чтобы загружать только код функции, когда это требуется . После вызова `autoload 'определение функции не читается. Функция просто отмечена как автозагрузка позже по мере необходимости.

И, наконец, примечание о $ FPATH и $ fpath: Zsh поддерживает их как связанные параметры. Параметр нижнего регистра представляет собой массив. Версия верхнего регистра представляет собой строковый скаляр, который содержит записи из связанного массива, соединенные двоеточиями между элементами. Это сделано, потому что обработка списка скаляров более естественна с использованием массивов, а также сохранение обратной совместимости для кода, использующего скалярный параметр. Если вы решите использовать $ FPATH (скалярный), вам нужно быть осторожным:

 FPATH=~/.zfunc:$FPATH 

будет работать, а следующее не будет:

 FPATH="~/.zfunc:$FPATH" 

Причина в том, что расширение тильды не выполняется в двойных кавычках. Вероятно, это источник ваших проблем. Если echo $FPATH печатает тильду, а не расширенный путь, то это не сработает. Чтобы быть в безопасности, я бы использовал $ HOME вместо тильды, как это:

 FPATH="$HOME/.zfunc:$FPATH" 

При этом я бы скорее использовал параметр массива, как я сделал в начале этого объяснения.

Вы также не должны экспортировать параметр $ FPATH. Это необходимо только текущему процессу оболочки, а не какому-либо из его дочерних элементов.

Обновить

Что касается содержимого файлов в `$ fpath ':

С автозагрузкой в ​​стиле zsh содержимое файла является телом функции, которую он определяет. Таким образом, файл с именем «hello» содержит строку echo "Hello world." полностью определяет функцию, называемую «привет». Вы можете поместить hello () { ... } вокруг кода, но это будет лишним.

Однако утверждение о том, что один файл может содержать только одну функцию, не совсем корректно.

Особенно, если вы посмотрите на некоторые функции из системы завершения на основе функций (compsys), вы быстро поймете, что это неправильное представление. Вы можете определить дополнительные функции в файле функций. Вы также можете выполнять любую инициализацию, что вам может понадобиться сделать в первый раз, когда вызывается функция. Однако, когда вы это сделаете, вы всегда определяете функцию, названную как файл в файле, и вызываете эту функцию в конце файла, поэтому она запускается при первом обращении к функции.

Если – с подфункциями – вы не определили функцию, названную как файл в файле, вы получите эту функцию, содержащую в ней функции определения (а именно функции подфункций в файле). Вы эффективно определяете все свои подфункции каждый раз, когда вы вызываете функцию, названную как файл. Обычно это не то, что вы хотите, так что вы переопределяете функцию, которая называется файлом в файле.

Я включу короткий скелет, который даст вам представление о том, как это работает:

 # 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 "$@" 

Если вы запустите этот глупый пример, первый запуск будет выглядеть так:

  zsh% hello
 инициализация ...
 Привет мир. 

И последовательные вызовы будут выглядеть так:

  zsh% hello
 Привет мир. 

Надеюсь, это прояснит ситуацию.

(Один из более сложных примеров реального мира, использующих все эти трюки, – это уже упомянутая функция ` _tmux 'из системы завершения функции на основе zsh.)

Имя файла в каталоге с fpath элемента fpath должно совпадать с именем определяемой автозагрузкой функции.

Ваша функция называется my_function а ~/.my_zsh_functions – это назначенный каталог в вашем fpath , поэтому определение my_function должно быть в файле ~/.my_zsh_functions/my_function .

Множественное число в предложенном имени файла ( functions_1 ) указывает, что вы планировали добавить в файл несколько функций. Это не то, как fpath и автозагрузка. У вас должно быть одно определение функции для каждого файла.

source ~/.my_zsh_functions/functions1 в терминале и оцените my_function , теперь вы сможете вызвать функцию

Вы можете «загрузить» файл со всеми вашими функциями в $ ZDOTDIR / .zshrc следующим образом:

 source $ZDOTDIR/functions_file 

Или можете использовать точку "." вместо «источника».

  • Команда Wrap в подсказке
  • Запись zsh и вывод на другую команду
  • zsh завершение: меню и однозначный префикс с одной вкладкой?
  • XTerm не обновляет изменения vim должным образом
  • Режим zsh vi: просмотр последних команд, начиная с
  • zsh: подстановка команды не наследует stdin из родительского
  • Как я могу остановить Z-оболочку от сговора, чтобы вмешаться в вывод GNU Make?
  • Установки завершения zsh (autojump) - Как их использовать?
  • Проверьте, запущен ли zshrc / sourced
  • zsh: отключить «файл существует:» предупреждение с перенаправлением
  • Разрешить все псевдонимы в командной строке zsh
  • Interesting Posts

    Повторить rsync, чтобы сохранить жесткие ссылки?

    GNOME-Terminal: создание новой вкладки терминала на удаленной машине

    Запустить xterm в текущий каталог через thunar

    Как определить, какой модуль повреждает ядро?

    Ручное управление выходом hdmi из Beaglebone / Raspberry

    Есть ли способ получить журналы для процессов запуска в /etc/init.d?

    Удалить последний символ из эхо-переменной

    Почему эта бомба вилка-раковины не работает на моей RHEL VM?

    CentOS – значение уровней / цветов индикатора уровня загрузочного экрана

    Как извлечь / удалить старые файлы из tarball, который был обновлен

    Как добавить свой собственный созданный центр сертификации в системные доверенные репозитории

    Как игнорировать пустые каталоги при использовании `rm` с подстановочными знаками для нескольких каталогов в zsh?

    rsync: использует ли невидимые файлы конфигурации?

    Обертывание псевдонимов в Bash

    Можно ли запустить Steam игры с помощью optirun?

    Linux и Unix - лучшая ОС в мире.