我一直在尝试将bash完成支持添加到我最近使用过的命令行程序中,但似乎我已经碰壁了。
以下是我想要自动完成的命令和子命令
主要命令为foo
,应对子命令version
,process
和help
执行自动完成。进一步的自动完成取决于子命令。
如果用户在主命令后输入-
,则自动完成会对这些字词执行完成:--activate
或--deactivate
如果用户输入--deactivate
,则应执行bash命令输出的自动完成(让我们说ls
)。
version
:未执行自动完成功能 process
:自动填充默认为列出目录(包括当前和父级)
-
,则自动完成会对这些字词执行完成:--color
,--verbose
然后停止如果用户输入help
,则自动完成功能适用于其他子命令(process
或version
)。
这是我当前实施的自动完成脚本(失败严重):
_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函数,但我现在还不知道该怎么做。如果您对如何实现这一点有任何建议,我将非常感激。
谢谢!
答案 0 :(得分:3)
如果第一级可能的子命令对我来说有点不清楚。
是否可以输入foo --activate
或foo - --activate
?后者看起来有些奇怪,但更适合您给定的代码。
第一个听起来更合理,但意味着将--activate
等作为一种全局参数,与你的子命令一样在同一级别上进行处理。
然而,当你还没有输入任何东西时,你错过了默认值。 请尝试以下代码:
_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)以不到达最终语句。
给出的示例将与foo - --activate
一起使用,这可能不是您想要的。
因此,如果您想输入foo --activate
,请将相应的行更改为
case "$prev" in
--activate)
COMPREPLY=()
return 0
;;
--deactivate)
COMPREPLY=( $(compgen -W "$(ls)" -- ${cur}) )
return 0
;;
version)
...