Bash 补全 -C 与 -F

Bash 补全 -C 与 -F

在 bash 完成设置中(https://github.com/scop/bash-completion)由我的系统提供,似乎对完成与complete -F相对的有明确的偏好complete -C

complete -p | grep -- -C # no match

两者之间的区别似乎在于,-F功能获取形式需要一个从变量读取输入并将其输出到变量的函数,而命令-C获取形式则从位置参数读取输入并输出到stdout

我更喜欢第二种方法,因为它更实用,并且完成函数/程序更容易调试(因为它们不依赖于特定的变量上下文)。

然而,https://github.com/scop/bash-completion对前者的偏好让我想知道:-C除了新流程的明显性能开销(对于 UI 来说可以忽略不计,恕我直言)之外,该方法是否还有任何缺点?

答案1

我不知道为什么你会认为complete -C {command}“更实用” complete -F {function},因为后者实际上需要一个函数;因此您所陈述的偏好的动机尚不清楚。但你是对的,几乎所有示例和文档都显示了对 的偏好complete ... -F {function} ...,例如complete -F _foobar foobar,该函数_foobar用于为假设的命令生成完成选项foobar

据推测,主要原因是:

  • 函数“ _foobar”可以用来完成多个命令,例如,也许一个foobar包也有一个foo和一个bar命令;$1传递给函数,以便您知道正在完成的命令的名称。
  • 函数变体似乎提供了更多信息来执行补全;-C相比之下,“ ”变体似乎更愚蠢(但是,不可否认,我-F自己一直使用“”变体。)
  • 通过函数(通过 COMPREPLY 数组变量)设置完成选项比依赖命令的输出更容易;该命令在子进程中运行,因此很难将信息传递到其中并从中获取信息。
  • “-C 命令”变体会生成一个子进程,当您真正希望感觉是瞬时的时,按“tab-tab-tab”完成时会产生额外的延迟。
  • “-C 命令”变体要么在complete语句中包含一个又长又复杂的命令,要么调用外部 shell 脚本,在这种情况下,您必须发送并跟踪该脚本的位置(这是一个痛苦的过程) )。

另外,在我个人的“完成”中,我必须让它们在旧版本的 bash 和各种 Unix(AIX、HP-UX、Solaris、Linux、BSD)上工作,并且我发现了很多不同的东西支持的。由于“ complete”在工作时返回true,所以我使用以下习惯用法,它似乎在 bash 版本之间更可移植(我只在此处包含此内容,因为它显示“ -F {function} {commmand}”的用法比相应的“”更简单/更干净-C "command"):

complete -o bashdefault -o default -o nospace -F _cmd cmd 2>/dev/null \
|| complete             -o default -o nospace -F _cmd cmd 2>/dev/null \
|| complete             -o default            -F _cmd cmd 2>/dev/null \
|| complete                                   -F _cmd cmd

同样,如果我有cmd1,,cmd2它们cmd3都采用基本相同的补全(例如,考虑一个和的补全脚本scpssh它采用你生成的主机名列表),

for c in cmd1 cmd2 cmd3; do
    # or that long complete statement shown above
    complete -o bashdefault -o default -o nospace -F _cmd $c 2>/dev/null
done

以供参考:

相关内容