在我的系统提供的 bash 完成设置(https://github.com/scop/bash-completion)中,似乎有一个明确的偏好来完成而complete -F
不是complete -C
.
complete -p | grep -- -C # no match
Run Code Online (Sandbox Code Playgroud)
两者之间的区别似乎在于,-F
取函数形式需要一个函数,该函数从变量中读取输入并输出到变量,而-C
命令形式从位置参数中读取输入并输出到stdout
。
我更喜欢第二种方法,因为它更实用,并且完成函数/程序更容易调试(因为它们不依赖于特定的变量上下文)。
但是,https://github.com/scop/bash-completion对前者的偏爱让我想知道:-C
除了新进程的明显(对于 UI,恕我直言,可以忽略不计)性能开销之外,这种方法还有什么缺点吗??
我不知道为什么你会认为complete -C {command}
“更实用” complete -F {function}
,因为后者实际上需要一个函数;因此您所陈述的偏好的动机尚不清楚。但你是对的,几乎所有示例和文档都显示了对 的偏好complete ... -F {function} ...
,例如complete -F _foobar foobar
,该函数_foobar
用于为假设的命令生成完成选项foobar
。
据推测,主要原因是:
_foobar
”可以用来完成多个命令,例如,也许一个foobar
包也有一个foo
和一个bar
命令;$1
传递给函数,以便您知道正在完成的命令的名称。-C
相比之下,“ ”变体似乎更愚蠢(但是,不可否认,我-F
自己一直使用“”变体。)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
Run Code Online (Sandbox Code Playgroud)
同样,如果我有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
Run Code Online (Sandbox Code Playgroud)
以供参考: