我在使bash完成脚本的行为符合预期方面遇到困难。
下面是我正在尝试做的最简化的版本,以及该问题的屏幕截图。
一切正常,除了一种情况:
当仅在完成项中有一个匹配项时,当我按两次Tab键时,它将打印两次相同的命令,这不是预期的效果。
在我的完成情况下,我只对完成第一个参数(即“子命令”)感兴趣。我认为下面的if [ "$#" -gt "2" ]
行本可以防止这种情况的发生,但事实并非如此-因为COMP_LINE
在第一个选项卡之后仍未更新。
#!/usr/bin/env bash
send_completions() {
if [[ -z "$COMP_LINE" ]]; then
return
fi
set $COMP_LINE
if [ "$#" -gt "2" ]; then
return
fi
compgen -W "one two test" "$2"
}
send_completions
通过运行以下命令启用完成:
$ complete -C './complete.sh' asd
然后键入asd o<tab><tab>
来查看问题。
感谢您的帮助。
答案 0 :(得分:1)
此刻检查COMP_LINE
的值:
$ asd one <TAB>
您会注意到该值为:
declare -x COMP_LINE="asd one "
发出set
后,这将导致两个位置参数,并且不会触发条件。尝试输入其他字符:$ asd one o<TAB>
,您会看到您的条件将被正确触发并且什么也不会完成。
我见过的大多数完成都是使用函数完成的。实际上,现在检查系统上定义的所有完成(大多数都是默认设置),其中的无是使用脚本完成的。
使用函数有一些好处,例如,尊重引用的COMP_WORDS
数组。您的脚本可以大致这样重写:
_asd_comp() {
(( COMP_CWORD > 1 )) && return
local cur=${COMP_WORDS[COMP_CWORD]} IFS=$' \t\n'
COMPREPLY=( $(compgen -W "one two three" -- "$cur") )
}
complete -o bashdefault -o default -F _asd_comp asd
我添加了-o
选项,以便在第一个参数之后执行默认补全。您可以在manual中了解更多相关信息。
我唯一想到的就是如何更改脚本,我想您可能会添加一些不干净的条件,例如:
(( $# > 1 )) && [[ ${COMP_LINE: -1} = " " ]] && return