假设我有一个命令“command”,它接受参数 foo:bar foo:foo bar:bar 或 bar:foo,我可以编写一个命令行完成脚本,可以将其放入我的环境中,给我提供如下所示的完成效果:
function _command_opt()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="foo:bar foo:foo bar:bar bar:foo"
if [[ ${prev: -7} == 'command' ]]
then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) );
return 0;
fi
}
complete -F _command_opt -o bashdefault -o default 'command'
但是如果我输入,command f[tab][tab]
我会得到列出的 foo:bar 和 foo:foo,但它们都不会在我的命令行上完成(因为它们尚未区分。我想要实现的是,这会产生command foo:
并将我的光标留在当前单词的末尾(而不是添加空格),以便我输入b
或f
然后再次按 Tab 键完成命令。示例问题只是为了说明我的意思……真实情况是前缀:后缀组合很长,因此部分完成将非常有益。例如,25 个不同的命令都以前缀 Translationupdateprocess: 开头,而 Translationupdateprocess 是 25 个不同的等长前缀之一,具有许多选项。
有谁知道如何让 bash 以这种方式完成运行?
答案1
您可以使用以下代码(foo:baz foo:qux bar:eat bar:egg
为了澄清起见,我替换了您的选项):
function _command_opt()
{
local cur cursec command opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
cursec=`echo ${cur} | awk -F ':' '{print $1}'`;
command="${COMP_WORDS[1]}"
opts="foo bar"
case "${command}" in
foo)
COMPREPLY=( $(compgen -W "baz qux" -- ${cursec}) ); return 0;;
bar)
COMPREPLY=( $(compgen -W "eat egg" -- ${cursec}) ); return 0;;
*) ;;
esac
COMPREPLY=( $(compgen -W "${opts}" -S ":" -- ${cur}) ); compopt -o nospace;
}
complete -F _command_opt -o bashdefault -o default 'command'
当你输入时,command
tab你可以获得第一级列表foo: bar:
,当你输入时,f
tabtab你可以获得第二级的完成列表baz qux
。然后,你可以输入q
tab以获取完整的命令行command foo:qux
。
希望能帮助到你。