嵌套bash自动补全脚本 [英] Nested bash autocompletion script
问题描述
我一直在尝试向最近使用的命令行程序添加bash补全支持,但是似乎我遇到了麻烦.
I've been trying to add bash completion support to a command line program I've been using lately, but it seems that I've hit a wall.
这是我要自动完成的命令和子命令
Here are the commands and subcommands I'd like to auto-complete
-
主要命令是
foo
,应该对子命令version
,process
和help 执行自动补全.代码>.进一步的完成取决于子命令.
Main command is
foo
, autocompletion should be performed for the subcommandsversion
,process
, andhelp
. Further autcompletion depends on the subcommand.
-
如果用户在主命令后输入
-
,则自动补全将对以下单词执行补全:-activate
或-deactivate
If the user enters
-
after the main command, autocompletion performs completion for these word:--activate
or--deactivate
如果用户输入-deactivate
,则应该执行bash命令输出的自动完成(例如 ls
).
If the user enters --deactivate
, it should perform autocompletion of a bash command output (let's say ls
).
进程
:自动补全默认为列出目录(包括当前目录和父目录)
process
: autocompletion defaults to listing directories (current and parent included)
- 如果用户输入
-
,则自动补全功能将对以下单词进行补全:-color
,-verbose
,然后停止
- If the user enters
-
, autocompletion performs completion for these words:--color
,--verbose
and then stops afterward
如果用户输入 help
,则自动完成将用于其他子命令( process
或 version
).
If the user enters help
, autocompletion is for the other subcommands (process
or version
).
这是我当前对自动完成脚本的实现(严重失败):
Here's my current implementation of the autocomplete script (which is failing badly):
_foo() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
words=("${COMP_WORDS[@]}")
cword=$COMP_WORD
opts="process version help"
case "$prev" in
-*)
local subopts="--activate --deactivate"
COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
case "$cur" in
--deactivate)
COMPREPLY=( $(ls) )
;;
esac
;;
version)
COMPREPLY=()
;;
process)
case "$cur" in
-*)
local subopts="--color --verbose"
COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
;;
*)
COMPREPLY=( $(compgen -A directory))
;;
esac
;;
help)
COMPREPLY=( $(compgen -W "process version" -- ${cur}) )
;;
esac
}
complete -F _foo foo
您可能会发现Bash并不是我的主要特长.我当时在考虑为每个子命令编写单独的bash函数,但是目前我不知道该怎么做.如果您也对如何实现此建议有任何建议,我将不胜感激.
You can probably see that Bash is not my main forte as well. I was thinking of writing separate bash functions for each subcommands, but I don't know how to do it at the moment. If you have suggestions on how to implement this as well, I would really appreciate it.
谢谢!
推荐答案
对于第一级可能存在的子命令,我不太清楚.是否可以输入 foo --activate
或 foo---activate
?后者看起来有些奇怪,但更适合您的给定代码.第一个听起来更合理,但暗示将-activate
等作为一种全局参数,可以像子命令一样在同一级别上对待.
In case of the possible subcommands on first level it's a bit unclear for me.
Should it be possible to enter foo --activate
or foo - --activate
? The latter looks somehow strange but fits more likely to your given code.
The first sounds more reasonable, but would imply to have --activate
etc. as kind of global parameter that is to be treated on the same level like your subcommands.
尽管如此,您还没有输入任何默认值,却错过了默认值.尝试以下代码:
Nevertheless you missed the default, when you haven't entered anything yet. Try the following code:
_foo() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
words=("${COMP_WORDS[@]}")
cword=$COMP_CWORD
opts="process version help"
case "$prev" in
-*)
local subopts="--activate --deactivate"
COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
case "$cur" in
--deactivate)
COMPREPLY=( $(ls) )
;;
esac
return 0
;;
version)
COMPREPLY=()
return 0
;;
process)
case "$cur" in
-*)
local subopts="--color --verbose"
COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
;;
*)
COMPREPLY=( $(compgen -A directory))
;;
esac
return 0
;;
help)
COMPREPLY=( $(compgen -W "process version" -- ${cur}) )
return 0
;;
esac
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
}
complete -F _foo foo
与您的基本相同,但:在底部,将COMPREPLY设置为您的第一级子命令,以使它们完成.如果输入了子命令,则应返回(0)以不到达最终语句.
which is basically the same as yours but: At the bottom, set COMPREPLY to your first level subcommands so they get completed. In case of having entered a subcommand, you should return (0) to not reach the final statement.
给出的示例将与 foo---activate
一起使用,这可能不是您想要的.因此,如果您想输入 foo --activate
,则将相应的行更改为
The example given will work with foo - --activate
which may not what you wanted.
So if you wanted to enter foo --activate
change the according lines to
case "$prev" in
--activate)
COMPREPLY=()
return 0
;;
--deactivate)
COMPREPLY=( $(compgen -W "$(ls)" -- ${cur}) )
return 0
;;
version)
...
这篇关于嵌套bash自动补全脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!