我正在尝试为可能需要表单上的长选项的命令编写一个 Bash 完成脚本--option
or --param=value
。如果用户已经在命令行上输入了一个选项,则该选项应从完成列表中排除(假设仅在命令行上指定一次给定选项才有意义)。
这是第一次尝试:
_myprog()
{
local cur="${COMP_WORDS[$COMP_CWORD]}"
local words=(--help --param1= --param-state --param2=)
_exclude_cmd_line_opts
COMPREPLY=( $(compgen -W "${words[*]}" -- "$cur") )
}
complete -F _myprog myprog
_exclude_cmd_line_opts() {
local len=$(($COMP_CWORD - 1))
local i
for i in "${COMP_WORDS[@]:1:$len}" ; do
[[ $i == --* ]] && words=( "${words[@]/$i}" )
done
}
如果源这个脚本source script.sh
然后写:
$ myprog --param1= <tab><tab>
我得到以下完成列表:
= --help --param2= --param-state
所以它几乎可以工作,除了我得到一个虚假的'='
登录完成列表..有什么建议吗?
由于默认内容,在命令行上输入等号会强制断词COMP_WORDBREAKS
。效果似乎是等号作为单独的单词输入COMP_WORDS
。这在以下修改中被利用_exclude_cmd_line_opts
:
_exclude_cmd_line_opts() {
local len=$(($COMP_CWORD - 1))
local i
for ((i=1 ; i<=len; i++)) ; do
local j="${COMP_WORDS[$i]}"
if [[ $j == --* ]] ; then
(( i<len )) && [[ ${COMP_WORDS[$(( i + 1))]} == '=' ]] && j="$j="
words=( "${words[@]/$j}" )
fi
done
}
原来版本的问题_exclude_cmd_line_opts
那是${words[@]/$j}
会给出一个虚假的=
例如当words=(param1=)
and j="param1"
(注意缺少尾随等号$j
这是由COMP_WORDBREAKS
)..
Update
我发现了这个的另一个特点。上面的例子工作得很好,因为我从来不需要打字<tab>
紧接着=
符号。但是,如果例如words=(--param= --param-info)
我输入--par<tab>
仍有两个候选完成,当前单词仅部分完成,成为--param
。此时我想选择两个候选者中的第一个,然后我输入一个明确的=
在命令行上签名,然后键入<tab>
现在发生的情况是 Bash 认为您输入了一个空格(因为 COMP_WORDBREAKS 包含=
) 并且当前完成词更改为--param=
to =
。这又会让 Bash readline 省略插入通常的空格,因此用户被迫输入空格来继续完成下一个选项。
通过返回一个可以避免在上述情况下键入空格COMPREPLY
带有空字符串的数组。
_myprog()
{
local cur="${COMP_WORDS[$COMP_CWORD]}"
local prev=""
(( COMP_CWORD > 0 )) && prev="${COMP_WORDS[$(( COMP_CWORD - 1))]}"
[[ $cur == '=' && $prev == --* ]] && { COMPREPLY=( "" ); return; }
local words=(--param= --param-info)
_exclude_cmd_line_opts
COMPREPLY=( $(compgen -W "${words[*]}" -- "$cur") )
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)