Bash 如何创建完整的三部分模式
我有一个命令行工具,它以三部分的形式接受参数:Bash 如何创建完整的三部分模式,bash,bash-completion,Bash,Bash Completion,我有一个命令行工具,它以三部分的形式接受参数: $ t first_second_third 我有一组适用于第一个的有效值,一组适用于第二个的有效值,以及一组适用于第三个的有效值。我想使用Bash complete功能来完成选项值的每个部分,如下例所示: $ t [tab][tab] # shows options for first part walk run skip bike $ t w[tab] # completes first par
$ t first_second_third
我有一组适用于第一个
的有效值,一组适用于第二个
的有效值,以及一组适用于第三个
的有效值。我想使用Bash complete功能来完成选项值的每个部分,如下例所示:
$ 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
$ t bike_[tab][tab]
home_ park_ work_
$ t bike_h[tab][tab]
home_ park_ work_
$ t bike_ho[tab][tab]
home_ park_ work_
我将第二个子句替换为以下内容(即,我在COMPREPLY
调用中将${cur}
替换为空字符串):
我在命令行上得到了所有选项的列表,但没有完成项
$ t [tab][tab]
bike_ run_ skip_ walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
$ 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
当然,我对第三部分也有同样的问题
--ap我能创造出你想要的东西。请参见下面的我的代码:
_tool () {
local cur="${COMP_WORDS[COMP_CWORD]}"
local first="walk run skip bike"
case "${cur}" in
*_*_*)
local firstsecond=`echo ${cur} | awk -F '_' '{print $1"_"$2}'`
local third="${firstsecond}_morning ${firstsecond}_afternoon ${firstsecond}_evening"
COMPREPLY=( $(compgen -W "${third}" -- ${cur}) ); return 0;;
*_*)
local firstcomp=`echo ${cur} | awk -F '_' '{print $1}'`
local second="${firstcomp}_home ${firstcomp}_work ${firstcomp}_park"
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
我对autocomplete不太熟悉,这是我第一次使用compgen
或complete
,所以我不确定我是否能回答你关于这个理论的问题。我可以告诉你我做了什么,以防它有助于你理解这些糟糕的函数是如何工作的。
首先,我试着理解你所拥有的。我成功地再现了你的问题。然后我有了这样的想法,即使你不想自己在代码中列出每一个排列,我也可以使用局部变量来模拟,就像它有一样。我做的第一件事是在我们有了第一个下划线之后得到“first”元素,并将第二个元素添加到其中,然后将其提供给compgen。令我惊讶的是,它工作得很好。然后我试着对第三级做同样的事情。。。然后问题开始了。我发现第二部分没有我想象的那么好。完成第一个单词后,我会得到第二个单词的建议;在选择一个单词作为第二个单词并点击[TAB]后,第一个下划线将消失
$ t [tab][tab] # shows options for first part
bike_ run_ skip_ walk_
$ t w[tab] # completes first part and appends delimiter
$ t walk_[tab][tab] # shows options for second part
walk_home_ walk_park_ walk_work_
$ t walk_h[tab] # completes second part and appends delimiter
$ t walk_home_[tab][tab] # screws up with it
$ t walkhome_
我尝试将下划线移到awk中,但没有成功:
local first=`echo ${cur} | awk -F '_' '{print $1"_"}'`
local second="${first}home ${first}work ${first}park"
出于某种原因,我不得不将变量名更改为与“first”不同的名称,它开始工作。然后,在第3个元素中,我遇到了与您上次描述的相同的问题,在第3个元素中键入的任何内容都将消失,但[tab][tab]将为我提供以下选项:
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_aft[tab] # erases what I typed
$ t walk_home_
在第三个单词中,我将
${cur}
添加到compgen中,它成功了。这只是我所做的总结。。。但我有一个工作版本,所以我很满意。:-) 我可以通过将特殊的$IFS
变量设置为包含\uu
字符来解决此问题?我需要试一试。嗨,亚历山大,看看下面我的答案,它应该很好用。我还添加了一个解释,以帮助您更好地理解它,因为我自己也不太理解它:DThanks,@msb。我会试一试,让你知道。bash completion是一个挑剔的野兽,有很多隐藏的陷阱,这就是为什么我使用bash completion框架,让你在yaml中定义你的完成层次,让框架为你解决复杂性