我有一个命令ts
,它将一个命令和该命令的参数作为其参数。我希望制表符补全能够“做正确的事情”,即:
例如,当我输入时,ts foo<tab>
bash 应该尝试自动完成并查找以 开头的任何命令foo
。我这样做是这样的:
complete -F __ts_bash_completions ts
__ts_bash_completions () {
COMPREPLY=();
# if there's only one word on the command line
if [ "$COMP_CWORD" -eq 1 ]; then
COMPREPLY=($(compgen -c -- "${COMP_WORDS[COMP_CWORD]}"));
一旦它有了完整的命令名称,我希望后续参数的制表符补全使用第一个参数的制表符补全语义。如果没有为第一个参数定义补全函数,我也可以正常工作。继续上面的操作,这有效:
# otherwise ...
else
local command_completion_function="$(complete -p ${COMP_WORDS[1]} 2>/dev/null|sed 's/.*-F \([^ ]*\) .*/\1/')"
if [ -z "$command_completion_function" ]; then
COMPREPLY=($(compgen -W "$(ls)" -- "${COMP_WORDS[COMP_CWORD]}"));
但我纠结的是最后一个要求,即如果有可用的完成函数,就应该使用它,但我就是无法让这个该死的东西工作。我看过这个问题和它的答案,并试图将其概括如下。再次继续上面的内容:
else
echo using $command_completion_function
echo COMP_CWORD="$COMP_CWORD"
echo COMP_LINE="$COMP_LINE"
echo COMP_WORDS="${COMP_WORDS[*]}"
COMP_CWORD=$(( $COMP_CWORD - 1 ))
COMP_LINE=$(echo $COMP_LINE|sed "s/^${COMP_WORDS[0]} //")
unset COMP_WORDS[0]
echo COMP_CWORD="$COMP_CWORD"
echo COMP_LINE="$COMP_LINE"
echo COMP_WORDS="${COMP_WORDS[*]}"
$command_completion_function
fi
fi
}
就我从各种变量来看一切看起来都正常,但有人能发现这个愚蠢的错误吗?echo
COMP_*
该
else
部分是这样的:我已经搞清楚了。错误在于,如果已经为命令定义了完成函数,我会调用它,但我没有处理它不返回任何内容的情况。我的测试用例是
ls
,在我的计算机上有...注意
-o bashdefault -o default
,如果函数没有设置,它将启动COMPREPLY
。-o bashdefault
表示“如果我们没有得到任何内容,则应用 bash 默认值”。-o default
表示“如果我们仍然没有得到任何内容,则应用 readline 默认值”。所以解决办法是在文件顶部这样写:
仅当作为第一个参数传递的命令为其完成定义它们时,才有可能应用它们的方法,但仅全局应用它们就足以满足我的用例了。
完整的固定脚本如下: