如何使用 bash 的 complete 或 compgen -C(命令)选项?

mat*_*tdm 9 bash autocomplete

在 bash 中创建 shell 完成功能时,该-C选项似乎非常强大且通用。它是这样定义的:

-C 命令

命令 在子shell环境中执行,其输出用作可能的完成。

这看起来真的很简单。但是,奇怪的是,事实并非如此。如果我做:

$ complete -C "echo one two three" test.sh
Run Code Online (Sandbox Code Playgroud)

然后输入test.sh并点击 [tab] 一次,我得到那一行

$ test.sh one two three test.sh  test.sh
Run Code Online (Sandbox Code Playgroud)

背部。什么?!为了比较,

$ complete -W "one two three" test.sh
Run Code Online (Sandbox Code Playgroud)

完全符合我的期望:它提供了一个三个两个尽可能的完成(当然是按排序顺序)。

我在任何地方都找不到任何好的文档,所以我正在尝试......也许分号有帮助?complete -C "echo one two three;" test.sh...啊,好吧,这对一些人有帮助,因为它test.sh从最后消除了奇怪的东西。但它仍然填写完整的 string one two three。这很奇怪,因为上面的描述肯定是说“可能的完成”,复数。...所以,嗯,啊,换行符?让我们试试complete -C "echo -e 'one\ntwo\nthree';" test.sh

好的,所以,这是有希望的。如果我打字test.sh [tab],我就会回来one three two。但接下来,事情就出错了。我添加一个o解决的模糊性,因此,test.sh o[tab]回报

o      one    three  two
Run Code Online (Sandbox Code Playgroud)

这令人费解。事实上,我输入的任何字符串都会被添加到列表中;如果我这样做test.sh wtf[tab],我会得到one three two wtf回应。我想我可能需要用 做一些复杂的事情compgen,但是,我再次强调,这与-W. 而且,事实上

$ complete -W '$(echo one two three)' test.sh
Run Code Online (Sandbox Code Playgroud)

工作得很好(注意单引号以防止过早扩展/执行,以防您做一些比echo可能产生可变结果更复杂的事情)。

我在这里缺少什么?

Gil*_*il' 10

-C命令的工作是确定要插入什么文本以响应完成请求。界面有点奇怪:

  • 的参数-C被解释为一个 bash 脚本片段。Bash 将三个正确引用的字符串附加到此代码段中:

    • 正在完成其参数的命令;
    • 光标所在单词的前缀,直到光标;
    • 光标前的单词。
  • 一些变量被添加到环境中:

    • COMP_LINE 包含执行完成的完整行。
    • COMP_POINT包含内部的光标位置COMP_LINE(从 0 开始计数)。
    • COMP_TYPE 是 9 表示正常完成,33 列出模糊完成的替代项,37 表示菜单完成,63 在模糊完成之间切换时,64 列出部分完成后的完成。
    • COMP_KEY包含触发完成的键(例如,如果用户按下了制表符Tab)。
  • 命令的输出被解释为文本以替换当前单词。请注意,这是一个替换,而不是附加的后缀;该命令应该按给定的前缀进行过滤。它可能包含多行,在这种情况下,每行都被视为可能的替换。

这大致是提供更好的相同的机制证明,与函数-F。函数获得了一个更理智的界面:它们可以读取COMP_WORDS变量中当前命令的单词列表,以及当前单词的起始位置COMP_CWORD;他们将结果写入COMPREPLY数组。

由于有用的参数——特别是要完成的前缀——在命令的末尾传递,-C几乎只能与外部命令一起使用。当然你可以使用类似的东西sh -c …,但它不会很漂亮。

complete -C 'sh -c '\'for x in one two three; do case $x in "$1"*) echo "$x";; esac''\'
Run Code Online (Sandbox Code Playgroud)