Как работает автозаполнение Bash?

9

Я могу понять, что автоматическое завершение bash работает для стандартных утилит. Но как это сделать автозаполнение для пользовательских программ, таких как Oracle SQL Loader?

В следующей команде, если вы нажмете Tab после control=этого, он автоматически заполняется до имени управляющего файла:

sqlldr kshitiz/oracle@XE control=data.ctl data=data.csv bad=data.bad log=data.log

Как он узнал, что должен заполнить контрольный файл в этот момент, а не какой-то другой файл?

Кшитиз Шарма
источник
2
Завершение параметров осуществляется с помощью функций. Большинство из них установлены в /etc/bash_completion.d. Посмотрите также /etc/bash_completionи посмотрите set, насколько выросла ваша среда.
ot--
@ott Что я должен искать в этом месте? Я не вижу ничего, связанного с sqlldr. Все у меня есть: gdbus-bash-completion.sh gvfs-bash-completion.sh pk-completion.bash yum.bash. Вывод setтакой же неинтересный.
Кшитиз Шарма
Это также может быть сделано в некотором сценарии из /etc/profile.d. Или, может быть, ваш .bash_profileили .bashrcбыл изменен.
ot--
Чем эти функции отличаются от нормальных функций? И как я могу определить свое собственное, чтобы обеспечить автоматическое заполнение для собственного скрипта? Не могли бы вы указать в правильном направлении?
Кшитиз Шарма
1
@KshitizSharma, bash-completionзагружает дополнения динамически с тех пор 1.90. Попробуйте: sqlldr<space><tab><enter>. Затем введите complete -p sqlldr.
Евгений Верещагин

Ответы:

6

Программируемое завершение Bash работает путем анализа командной строки и выяснения того, что завершается:

  1. Некоторые контексты обрабатываются особым образом, например, первое слово в команде завершается как имя команды, последующее a $завершается как имя переменной и т. Д.
  2. Вне этих контекстов bash пытается завершить аргумент команды, и применяются параметры команды или сбой (что обычно имеет место) для базового имени команды.

Например, после , bash завершает имена команд, начинающиеся с . После bash завершает имена переменных, которые начинаются с . После bash применяет правила завершения для команды . Правила завершения могут указывать категорию (пользователь, переменную, файлы и т. Д.), Шаблон подстановочного знака для имен файлов или функцию или фрагмент кода для выполнения.sqllTabsqllsqlldr $aTabasqlldr Tabsqlldr

Правила завершения определяются completeвстроенным. Bash не отслеживает, когда completeбыл вызван встроенный модуль или в каком скрипте (если он есть) он был. В большинстве дистрибутивов поставляется пакет завершения bash , который предоставляет ряд правил для общих команд. Это принимает форму ряда файлов сценариев, которые содержат вызовы complete, со сценарием, который должен быть прочитан .bashrc(или /etc/bash.bashrcреализован) для загрузки всех этих сценариев: обычно . /etc/bash_completionтребуется для активации программируемого завершения и загрузки доступных сценариев.

Стандартный пакет не включает поддержку sqlldr. Если у вас есть такая поддержка, она должна исходить из другого источника. Этот источник , возможно, уронил файл в каталоге , как /etc/bash_completion.dи мог бы прийти с инструкциями , чтобы включить некоторый код в вашем .bashrc. Вы можете использовать, complete -p sqlldrчтобы увидеть текущие правила для sqlldr; как упоминалось ранее, это не скажет вам, откуда были загружены эти правила.

Tcsh, zsh и fish имеют несколько схожих механизмов (все черпали вдохновение в tcsh), но имеют различные встроенные функции, синтаксис и возможности.

Жиль "ТАК - перестань быть злым"
источник
да, вы не можете найти, где completeбыл вызван. Но вы можете найти имя исходного файла и номер строки, где определена функция завершения. complete -p sudo # outputs complete -F _sudo sudo, shopt -s extdebug, declare -F _sudo # outputs _sudo 3 /usr/share/bash-completion/completions/sudo. (Но см. Мой комментарий о динамически завершающих загрузках и complete -p).
Евгений Верещагин
and the settings for the basename of the command are applied, Нет. Вы можете иметь разные compspecs для dateи /bin/date. Справочник гласит : Если командное слово является полным путем, сначала ищется compspec для полного имени пути. Если для полного пути не найден compspec, делается попытка найти compspec для части, следующей за последней косой чертой
Евгений Верещагин