Автоопределение возможных аргументов в сценарии оболочки для завершения

Вот сценарий оболочки, который делает некоторые вещи в соответствии с тем, с каким параметром он был вызван:

if [ $1 = "-add" ] 
then
    ...
elif [ $1 = "-remove" ]
    ...
else
    ...
fi

Скрипт является исполняемым (ссылка на него была создана в /usr/bin каталог). Итак, я могу вызвать его из оболочки, указав имя ссылки, добавленной в /usr/bin,

Что я хочу, так это автоматическое определение возможных аргументов скрипта (в моем случае они -add, -removeво время звонка. Это означает, что когда я наберу команду, связанную с вызовом скрипта, то наберу -re и нажмите кнопку вкладки, это предложит, что это -remove и автозаполните это для меня.

Как аргументы должны быть определены, чтобы достичь этого?

Пытался создать псевдонимы в файле конфигурации оболочки или несколько ссылок в /usr/bin каталог для всех возможных входов, и он работал нормально, но я не думаю, что это лучшее решение для этого.

2 ответа

Хотя это требует некоторой настройки вне вашего скрипта, добавить опции автозаполнения довольно просто.

Вот простой пример файла ~/.bash_completion, который добавляет автозаполнение --add и --remove для команды yourscript. В реальном случае вы, вероятно, захотите сгенерировать параметры, напрямую запросив скрипт; они жестко запрограммированы здесь для простоты.

_yourscript_complete()
{
    # list of options for your script
    local options="--add --remove"

    # current word being completed (provided by stock bash completion)
    local current_word="${COMP_WORDS[COMP_CWORD]}"

    # create list of possible matches and store to ${COMREPLY[@}}
    COMPREPLY=($(compgen -W "${options}" -- "$current_word"))
}
complete -F _yourscript_complete yourscript

Обратите внимание, что ~/.bash_completion создается только во время входа в систему, поэтому вам нужно будет создать другую оболочку входа в систему, чтобы увидеть изменения в действии. Возможно, вам также потребуется включить поиск файлов пользователя bash_completion в вашей системе.

Результат:

$ yourscript --<tab><tab>
--add     --remove

Кажется, что завершение bash/zsh - это мощный инструмент, который может управлять вводом данных в оболочку так, как вы хотите.

В одном из других ответов были представлены некоторые пояснения о том, как это работает в bash.

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

  1. Настройка .zshrc файл:

    • добавление папки для ваших функций автозаполнения:

      fpath=(~/.zsh-completions $fpath)

    • включение zsh tab-complete system:

      autoload -U compinit & compinit

    Примечание: надстрочные строки должны быть добавлены к ~/.zshrc файл.

  2. Добавление функции для вашего скрипта:

    После настройки файла.zshrc перезапустите zsh и введите scriptname в нем функция compinit() выведет список всех файлов с $fpath и найти тот, у которого первая строка совпадает #compdef scriptname,

    Итак, новый файл _scriptname который будет содержать функцию для нашего скрипта должен быть добавлен в ~/.zsh-completions каталог. Чтобы позволить compinit() найти этот файл на scriptname набрав, как упоминалось выше, его первая строка должна быть: #compdef scriptname,

  3. Пусть аргументы танцуют

    Для zsh есть много примеров функций завершения в /usr/share/zsh/functions/Completion каталог. Найдя подходящий там, вы можете настроить вход оболочки в соответствии со своими вкусами. Для автоматического определения атрибутов (в моем случае они -add а также -remove) _attributes() функция в _scriptname Файл может быть установлен следующим образом:

    _arguments -s \            
    '(-a --add)'{-a,--add}'[adding a new item to the basket]' \
    '(-r --remove)'{-r,--remove}'[removing an item from the basket]'
    

В конце концов, после перезапуска Zsh снова, автоопределение для scriptname работает как показано ниже:

scriptname -<TAB>   => scriptname -      
                       --add     -a  -- adding a new item to the basket                  
                       --remove  -r  -- removing an item from the basket

scriptname --a<TAB> => scriptname --add 
scriptname --r<TAB> => scriptname --remove
Другие вопросы по тегам