如何自动完成别名为单个命令的多级命令?

8

假设我有两个bash函数:

dock() { sudo docker $@ ;}

并且

dock-ip() { sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' $@ ;}

如何让bash自动补全与第二个函数一起工作?
对于第一个函数,只需添加以下内容即可:
_completion_loader docker; complete -F _docker dock

这对第二个命令无效。Docker的自动补全源位于Debian Stretch上的/usr/share/bash-completion/completions/docker中。我还有更多像dock-rundock-exec等的功能,所以我不想为它们中的每一个编写自定义完成函数。
此外,complete -F _docker_container_inspect dock-ip只部分起作用; tab仅列出容器,而不是完成部分字符串。
研究: 如何自动完成嵌套的多级子命令? <-- 需要自定义函数 https://superuser.com/questions/436314/how-can-i-get-bash-to-perform-tab-completion-for-my-aliases <-- 仅针对顶层命令自动化
1个回答

4

通过总共一小时的bash自动补全经验,我分析了docker自动补全脚本(/usr/share/bash-completion/completions/docker)和bash_completion.sh脚本,并创建了一个包装函数:

# Usage:
#   docker_alias_completion_wrapper <completion function> <alias/function name>
#
# Example:
#   dock-ip() { docker inspect --format '{{ .NetworkSettings.IPAddress }}' $@ ;}
#   docker_alias_completion_wrapper __docker_complete_containers_running dock-ip
function docker_alias_completion_wrapper {
  local completion_function="$1";
  local alias_name="$2";

  local func=$(cat <<EOT
    # Generate a new completion function name
    function _$alias_name() {
        # Start off like _docker()
        local previous_extglob_setting=\$(shopt -p extglob);
        shopt -s extglob;

        # Populate \$cur, \$prev, \$words, \$cword
        _get_comp_words_by_ref -n : cur prev words cword;

        # Declare and execute
        declare -F $completion_function >/dev/null && $completion_function;

        eval "\$previous_extglob_setting";
        return 0;
    };
EOT
  );
  eval "$func";

  # Register the alias completion function
  complete -F _$alias_name $alias_name
}
export -f docker_alias_completion_wrapper

我随后创建了我的别名/函数,如下所示:

# Get container IP
dock-ip() { docker inspect --format '{{ .NetworkSettings.IPAddress }}' $@ ;}
docker_alias_completion_wrapper __docker_complete_containers_running dock-ip

# Execute interactive container
dock-exec()  { docker exec -i -t --privileged $@ ;}
docker_alias_completion_wrapper __docker_complete_containers_all dock-exec

... 

请确保在您的个人别名脚本顶部调用_completion_loader docker;来加载主要的Docker完成脚本。我邀请更多熟练的Bash程序员来改进这个答案。

_completion_loader docker; 这行代码加到你的第一个示例代码里,这样更懒人友好 :P - Andrzej Piszczek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接