2013-04-07 56 views
3

我添加了一个新的别名scp_using_rsync,它使用rsync通过SSH将文件复制到特定选项。我想把scp的bash完成连接到这个别名。bash完成 - 在第一次调用命令时定义的完成功能

它的工作原理,当我加入这一行:

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那个外壳。所以如果我直接在新shell中运行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的bash完成?

回答

5

Bash 4.1增加了一个新-D选项completecompgencompopt

新完整/ 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的手册:[Programmable Completion](http:// www。 gnu.org/software/bash/manual/bashref.html#Programmable-Completion) – pynexj 2013-04-07 05:14:30

+0

哇!不知道bash有一个选项可以即时加载新的完成。你是对的,我看到'/ usr/share/bash-completion/bash_completion'中定义了'_completion_loader()'函数,这似乎是源于'/ usr/share/bash-completion/bash_completion'中的所有文件,因此ssh/scp的完成会被加载。甜! :)我认为对于我的用例,我会覆盖并定义自己的完成加载器来定义预期的完成,然后在bash完成中调用它。 – Tuxdude 2013-04-07 05:16:45

2

我不得不申请whjm的答案的问题。正如Tuxdude注意到的那样,在我的发行版(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功能,然后添加完成你的命令。我觉得这是一个更直接和一致的方式(虽然当然要做到这一点,但您必须为所有用户更改此行为。)