如何将Shell补全推迟到bash和zsh中的另一个命令?

Jac*_*pie 12 bash zsh bash-completion zsh-completion completion

我试图编写一个将其他Shell实用程序包装到单个CLI中的Shell脚本实用程序,并试图使Shell完成在zsh和bash中工作。

例如,假设CLI名为util

util aws [...args] #=> runs aws
util docker [...args] #=> runs docker
util terraform [...args] #=> runs terraform
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想要的是zsh和bash补全中的一种方式,它能够独立于包装脚本的补全实现说“像其他命令Y一样完成此子命令X”。

就像是:

compdef 'util aws'='aws'
compdef 'util docker'='docker'
compdef 'util terraform'='terraform'
Run Code Online (Sandbox Code Playgroud)

扩展目标将是允许对另一个二进制文件中的子命令完成任意子命令:

util aws [...args] #=> completes against `aws`
util ecr [...args] #=> completes against `aws ecr`
Run Code Online (Sandbox Code Playgroud)

有可能吗?我一直在尝试模拟单个二进制文件的完成脚本,但是在编写其他完成脚本的方式上有很大的不同。

Nat*_*eks 5

我对 zsh 一无所知,但我可以为 bash 提供解决方案。它委托使用该_complete函数(我发现这是遵循muru 的建议- 很好的选择!)。

该函数的第二部分提供util命令本身的补全,我假设这里只是子命令的列表。当然,您可以根据您的需要进行定制。

第一部分在已键入完整子命令的情况下处理委托,并可选择根据子命令的完成情况处理完成目标。

功能

_delegate() {
  local cur subs
  cur="${COMP_WORDS[COMP_CWORD]}" # partial word, if any
  subs="ssh aws docker terraform"
  if [[ $COMP_CWORD == 2 ]]; then
    # Two whole words before the cursor - delegate to the second arg
    _command $2
  else
    # complete with the list of subcommands 
    COMPREPLY=( $(compgen -W "${subs}" -- ${cur}) )
  fi
}
Run Code Online (Sandbox Code Playgroud)

安装

njv@pandion:~$ complete -F _delegate util
Run Code Online (Sandbox Code Playgroud)

演示

1d [njv@eidolon:~] $ util
aws        docker     ssh        terraform
1d [njv@eidolon:~] $ util ssh
::1                        gh                         ip6-localhost              ubuntu.members.linode.com
eidolon                    github.com                 ip6-loopback
ff02::1                    ip6-allnodes               localhost
ff02::2                    ip6-allrouters             ubuntu
1d [njv@eidolon:~] $ util ssh ip6-
ip6-allnodes    ip6-allrouters  ip6-localhost   ip6-loopback
Run Code Online (Sandbox Code Playgroud)