bash-completion — функция завершения, определяемая при первом вызове команды

Я добавил новый псевдоним scp_using_rsync, который использует rsync для копирования файлов по SSH с определенными параметрами. Я хотел связать завершение bash для scp с этим псевдонимом.

Это работает, когда я добавляю эту строку:

complete -o bashdefault -o default -o nospace -F _scp scp_using_rsync 2>/dev/null || complete -o default -o nospace -F _scp scp_using_rsync

Единственная проблема заключается в том, что я замечаю, что _scp определяется в моей среде bash только после того, как я хотя бы один раз пытаюсь завершить табуляцию с помощью ssh/scp в этой оболочке. Поэтому, если я напрямую запущу scp_using_rsync в новой оболочке, я получу ошибку _scp not found.

Вывод из typeset -F в новой оболочке до и после попытки завершения табуляции для команд ssh или scp ясно показывает, что следующие функции определяются после первой попытки автодополнения табуляции:

$ diff ~/.scratch/file1 ~/.scratch/file2
224a225,227
> declare -f _scp
> declare -f _scp_local_files
> declare -f _scp_remote_files
226a230
> declare -f _sftp
230a235,240
> declare -f _ssh
> declare -f _ssh_ciphers
> declare -f _ssh_macs
> declare -f _ssh_options
> declare -f _ssh_suboption
> declare -f _ssh_suboption_check

Эти функции, кажется, определены в /usr/share/bash-completion/completions/ssh в моей системе.

Это мои 2 взаимосвязанных вопроса:

  • Как bash определяет, где автоматически брать определения и определять их при первой попытке завершения?
  • Как я должен связать завершение bash для scp_using_rsync с завершением bash scp аналогичным образом?

person Tuxdude    schedule 07.04.2013    source источник


Ответы (3)


Bash 4.1 добавил новую опцию -D для complete, compgen и compopt:

Новая опция complete/compgen/compopt -D для определения завершения по умолчанию: дополнение, которое будет вызываться для команды, для которой не было определено завершение. Если эта функция возвращает 124, программируемое завершение предпринимается снова, позволяя пользователю динамически создавать наборы завершений по мере попытки завершения, когда функция завершения по умолчанию устанавливает отдельные функции завершения. каждый раз, когда он вызывается.

Пример из руководства по bash:

_completion_loader()
{
     . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
}
complete -D -F _completion_loader
person pynexj    schedule 07.04.2013
comment
Ух ты! не знал, что в bash есть возможность загружать новые дополнения на лету. Вы правы, я вижу функцию _completion_loader(), определенную в /usr/share/bash-completion/bash_completion, которая, кажется, получает все файлы в /usr/share/bash-completion/bash_completion и, следовательно, загружаются дополнения для ssh/scp. Сладкий! :) Я думаю, что для моего случая использования я переопределю и определю свой собственный загрузчик завершения, чтобы определить предполагаемые завершения, а затем вызову тот, который находится в bash-completion. - person Tuxdude; 07.04.2013
comment
Я не понимаю, как это использовать. Я попытался запустить код выше. Но когда я набираю d rm <TAB>, я все равно получаю ошибку bash: completion: function '_docker' not found. (Убунту 16.04, Баш 4.3.48) - person wisbucky; 27.07.2018

У меня возникла проблема с применением ответа whjm. Как заметил Tuxdude, в моем дистрибутиве (Ubuntu 14.04) уже была определена функция _completion_loader. Функция была определена следующим образом:

_completion_loader () 
{ 
    local compfile=./completions;
    [[ $BASH_SOURCE == */* ]] && compfile="${BASH_SOURCE%/*}/completions";
    compfile+="/${1##*/}";
    [[ -f "$compfile" ]] && . "$compfile" &> /dev/null && return 124;
    complete -F _minimal "$1" && return 124
}

Я хотел, чтобы поддержка всех дополнений хранилась в одном месте, поэтому я добавил файл в /usr/share/bash-completion/completions/ с именем команды, для которой я хотел добавить завершение. В вашем случае вы можете добавить файл с именем scp_using_rsync, содержащий это:

cfile="${compfile%/*}/scp"
cmd="${1##*/}"
. "$cfile" 
complete -F _scp $cmd

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

person slevin    schedule 19.05.2014

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

_completion_loader docker

person wisbucky    schedule 26.07.2018