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

Я добавил новый псевдоним 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 не найдена ошибка.

Выход из 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 подобным образом завершить работу scp?

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

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

_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 функции, а затем добавьте завершение для вашей команды. Я чувствовал, что это более прямой и последовательный способ (хотя, конечно, чтобы сделать это, вы должны согласиться с изменением этого поведения для всех пользователей.)

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

_completion_loader docker

Другие вопросы по тегам