我有一个程序,foo
就像许多其他程序一样,它采用以下形式的命令行参数:
foo
[选项]命令...
在哪里选项是零个或多个短(例如,-s
)或长(例如,--long
)样式选项,后跟正好一个命令关键字后跟该命令的参数。
我想要一个 Bash 完成功能,可以完成长选项或命令。方便地,foo
还采用--options
打印其选项列表和--commands
打印其命令列表的选项。
我希望该功能能够提供建议仅有的对于第一个非选项词(命令) 在命令行上并提供不键入时对后续单词的建议tab。
使用部分这个答案,我尝试COMP_CWORD
仅在其值为 1 时使用并执行补全。这是到目前为止我的补全函数:
_foo() {
local cur=${COMP_WORDS[COMP_CWORD]}
if [[ "$cur" == -* ]]
then COMPREPLY=($(compgen -W "$(foo --options)" -- $cur))
else
if (( COMP_CWORD == 1 ))
then COMPREPLY=($(compgen -W "$(foo --commands)" -- $cur))
else COMPREPLY=()
fi
fi
}
这几乎作品。但是,如果用户在命令喜欢:
foo --long
tab
然后按tab,外壳发出蜂鸣声。我认为这是因为COMP_CWORD
此时为 2,因为它不区分选项和非选项。
好的,那么我想让该函数扫描当前单词之前的所有单词,并减去以-
这样的开头的单词数:
_foo() {
local cur=${COMP_WORDS[COMP_CWORD]}
if [[ "$cur" == -* ]]
then
COMPREPLY=($(compgen -W "$(foo --options)" -- $cur))
else
local i=$COMP_CWORD
while (( i > 1 ))
do
[[ "${COMP_WORDS[i-1]}" != -* ]] && break
((--i))
done
if (( i == 1 ))
then COMPREPLY=($(compgen -W "$(foo --commands)" -- $cur))
else COMPREPLY=()
fi
fi
}
这是可行的,但问题是,如果用户给出一个简短的选项,该选项接受一个参数并提供所述参数作为下一个单词,例如:
foo -s arg
tab
那么索引就会减一。完成函数必须详细了解所有选项,无论它们是否带有参数,并且必须有效地解析所有选项以获得正确的索引。
这看起来工作量很大。有没有更简单的方法让我的补全功能只为第一个非选项词提供建议?或者只是放弃并总是提供建议?