bash-completion - 在第一次调用命令时定义的completion函数

时间:2013-04-07 02:34:29

标签: bash bash-completion

我添加了一个新的别名scp_using_rsync,它使用rsync通过SSH复制文件并使用某些选项。我想将scp的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中至少执行一次tab-completion之后。因此,如果我在新shell中直接运行scp_using_rsync,我会收到_scp未找到的错误。

在为ssh或scp命令尝试制表符完成之前和之后,新shell中typeset -F的输出清楚地表明在第一次尝试制表完成后会定义以下函数:

$ 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中定义。

这是我的两个相互关联的问题:

  • bash如何自动获取定义的位置,并在第一次尝试完成时定义它们?
  • 我应该如何以类似的方式将scp_using_rsync的bash-completion与scp的bash完成相关联?

3 个答案:

答案 0 :(得分:6)

Bash 4.1-Dcompletecompgen添加了新的compopt选项:

  

用于定义“默认”完成的新的complete / compgen / compopt -D选项:       要在没有完成的命令上调用的完成       定义即可。如果此函数返回 124 ,则可编程完成       再次尝试,允许用户动态构建一组完成       通过具有默认完成功能来尝试完成       每次调用时都安装各个完成函数。

有一个来自bash的manual

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

答案 1 :(得分:3)

我在应用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函数,然后为命令添加完成。我觉得这是一种更直接,更一致的方式(当然,要做到这一点,你必须为所有用户改变这种行为。)

答案 2 :(得分:0)

一些完成功能是动态加载的。您可以手动加载它们,以便它们可以使用别名。例如,您可以将其添加到~/.bashrc中,以便使用别名进行补全。

_completion_loader docker