2013-04-07 4 views
3

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

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

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 получает определенные в моей Баш среде, только после того, как я пытаюсь вкладки-завершения с SSH/УПП по крайней мере один раз в эта оболочка. Поэтому, если я непосредственно запускаю 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-завершения для scp_using_rsync с завершением bash scp аналогичным образом?

ответ

5

Bash 4.1 добавлен новый -D вариант для complete, compgen и compopt:

Новая опция в комплекте/CompGen/compopt -D для определения `по умолчанию» завершение: завершение будет ссылаться на команда, для которой не было завершено . Если эта функция возвращает , программируемое завершение является снова попытка, позволяя пользователю динамически создавать набор доработок как завершение попытка имея функцию завершения по умолчанию установить отдельные функции ЗАВЕРШЕНИЕ каждый раз, когда она вызывается.

Там пример из руководства по BASH:

_completion_loader() 
{ 
    . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124 
} 
complete -D -F _completion_loader 
+0

Ссылка на руководство по bash: [Программируемое завершение] (http: // www. gnu.org/software/bash/manual/bashref.html#Programmable-Completion) – pynexj

+0

Вау! не знал, что у bash была опция загрузки новых доработок «на лету». Вы правы, я вижу функцию '_completion_loader()', определенную в '/ usr/share/bash-completion/bash_completion', которая, кажется, отправляет все файлы в'/usr/share/bash-completion/bash_completion' и, следовательно, пополнения для ssh/scp загружаются. Милая! :) Я думаю, что для моего случая использования я переопределяю и определяю свой собственный загрузчик завершения для определения предполагаемых завершений, а затем вызываю его в bash-завершении. – Tuxdude

2

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