如何在bash和zsh中将Shell完成延迟到另一个命令?

14

我正在尝试编写一个 shell 脚本实用程序,将其他 shell 实用程序包装成单个 CLI,并尝试在 zsh 和 bash 中使 shell 自动完成工作。

例如,假设 CLI 名为 util


util aws [...args] #=> runs aws
util docker [...args] #=> runs docker
util terraform [...args] #=> runs terraform
我理想中希望在 zsh 和 bash 的自动补全功能中,能够独立于所包装的脚本实现,并且可以像完成其他命令 Y 一样,完成子命令 X。类似于:

complete -X like Y

compdef 'util aws'='aws'
compdef 'util docker'='docker'
compdef 'util terraform'='terraform'

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

util aws [...args] #=> completes against `aws`
util ecr [...args] #=> completes against `aws ecr`

这是否可能?我一直在尝试模拟各个二进制文件的完成脚本,但是其他完成脚本的编写方式存在显着差异。


2
你最好为bash和zsh分别提出两个问题,不要期望一个人都能很好地掌握它们两个。 - user8680478
1
请在您的问题中添加操作系统或Linux发行版及其版本。 - Cyrus
@Cyrus - 这是关于Bash或Zsh的问题,它们在不同的操作系统或发行版之间都是可移植的。 - Jacob Gillespie
3
或许值得研究一下 zsh 是如何处理 sudo 命令的补全的。在我的情况下,输入 sudo foo <tab> 会显示 foo 的补全选项。也许一个懒惰的解决办法是使用 compdef util=sudo。请注意保持原文意思不变,同时使翻译更通俗易懂。 - muru
1个回答

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
}

安装

njv@pandion:~$ complete -F _delegate util

演示

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

我相信你的“超额目标”也是可能实现的,但我仍在努力寻找一个好的方法。如果我很快找到了,我会更新我的答案 :) - Nathan Vērzemnieks

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