我有一个命令行工具,它以三部分形式接受参数:
$ t first_second_third
我有一组有效值first
,一组有效值second
,一组有效值third
。我想使用 Bash 完整功能来完成选项值的每个部分,如下例所示:
$ t [tab][tab] # shows options for first part
walk run skip bike
$ t w[tab] # completes first part and appends delimiter
$ t walk_[tab][tab] # shows options for second part
home work park
$ t walk_h[tab] # completes second part and appends delimiter
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_a[tab] # completes second part and appends space
$ t walk_home_afternoon
我有这个代码:
_tool () {
local cur="${COMP_WORDS[COMP_CWORD]}"
local first="walk run skip bike"
local second="home work park"
local third="morning afternoon evening"
case "${cur}" in
*_*_*)
COMPREPLY=( $(compgen -W "${third}" -- "") ); return 0;;
*_*)
COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
*)
COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
esac
}
complete -F _tool t
第一个子句效果很好;那里没什么特别的。但是第二个子句没有给我任何选择或完成。
$ t [tab][tab]
bike_ run_ skip_ walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
我将第二个子句替换为以下内容(即,我${cur}
在调用中替换为空字符串COMPREPLY
):
COMPREPLY=( $(compgen -W "${second}" -S "_" -- "") ); compopt -o nospace; return 0;;
我在命令行上获得了所有选项的列表,但没有完成。
$ t bike_[tab][tab]
home_ park_ work_
$ t bike_h[tab][tab]
home_ park_ work_
$ t bike_ho[tab][tab]
home_ park_ work_
我认为可能与单词列表有一些不好的交互${cur}
,COMPREPLY
所以我再次更改了第二个子句,添加了一个与当前单词的第一部分匹配的前缀:
local prefix=( $(expr "${cur}" : '\(.*_\)') )
COMPREPLY=( $(compgen -W "${second}" -P "${prefix}" -S "_" -- "") ); compopt -o nospace; return 0;;
这没有多大帮助。${cur}
仍然在命令COMPREPLY
中,我再次没有选项或完成。相反,使用空字符串,我得到了完整的选项(不仅仅是当前部分)。但是,按 Tab 会删除键入的内容。
$ t bike_[tab][tab]
bike_home_ bike_park_ bike_work_
$ t bike_ho[tab]
$ t bike_ # "ho" was erased
当然,我对第三部分也有同样的问题。
- 如何让 Bash 部分地完成当前单词?
- 在选择一个选项之前,如何让 Bash 不附加分隔符?
这类似于另一个 Bash 完整问题,但我不想列出所有可能的值排列,并且它们没有格式化为文件名(不确定文件名模式是否有所不同)。
谢谢您的帮助!
--ap