在 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
都采用基本相同的补全(例如,考虑一个和的补全脚本scp
,ssh
它采用你生成的主机名列表),
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
以供参考: