任意深度嵌套的自动完成

Arbitrarily deep nested autocomplete

我已经尝试(并且悲惨地失败了)编写一个 bash 可以进行任意深度自动完成的完成脚本。尽管阅读了多篇 SO 帖子以及一些博客和文档,我还是没能超过两点 :-\。例如,我可以到达:

$ seuss tweedle beetle

但无法到达 seuss tweedle beetle puddle

我什至不需要在每个完成的末尾使用函数,只需要选项本身。我尝试修改以下帖子中的脚本,但我所做的一切都会崩溃。

Nested bash autocompletion script

How do I autocomplete nested, multi-level subcommands?

这是我尝试过的方法:

_seuss()
{
    local one two three four

    one=${COMP_WORDS[COMP_CWORD]}
    two=${COMP_WORDS[COMP_CWORD-1]}
    three=${COMP_WORDS[COMP_CWORD-2]}
    four=${COMP_WORDS[COMP_CWORD-3]}

    case ${COMP_CWORD} in
        1)
            COMPREPLY=($(compgen -W "fox tweedle" -- ${one}))
            ;;
        2)
            case ${two} in
                fox)
                    COMPREPLY=($(compgen -W "socks" -- ${one}))
                    case ${three} in
                        socks)
                            COMPREPLY=($(compgen -W "box clocks" -- ${one}))
                            ;;
                        box)
                            COMPREPLY=($(compgen -W "knox" -- ${one}))
                            ;;
                    esac
                    ;;
                tweedle)
                    COMPREPLY=($(compgen -W "beetle poodle" -- ${one}))
                    case ${three} in
                        beetle)
                            COMPREPLY=($(compgen -W "puddle battle" -- ${one}))
                            ;;
                        poddle)
                            COMPREPLY=($(compgen -W "noodle" -- ${one}))
                            ;;
                    esac
                    ;;
            esac
            ;;
        *)
            COMPREPLY=()
            ;;
    esac
}

complete -F _seuss seuss

但这只会导致:

$ seuss fox sox

我似乎无法获得 box clocks

逻辑有问题。我建议您使用 printf 函数进行调试,并仔细考虑实际发生的情况。我刚刚添加了以下代码作为 _seuss 函数的最后一行:

printf "\n*** DEBUG ***\nCOMP_CWORD: $COMP_CWORD\nOne: $one\nTwo: $two\nThree: $three\nFour: $four\nCOMP_LINE: $COMP_LINE"

现在,当您调用 $ seuss fox socks <TAB> 时,您可以看到所有变量是如何填满的:

*** DEBUG ***
COMP_CWORD: 3
One: 
Two: socks
Three: fox
Four: seuss
COMP_LINE: seuss fox socks

因此,如您所见,当 COMP_CWORD3 时没有设置规则。只是一个普通的旧 COMPREPLY=(),这意味着不会打印任何建议。使用此 printf 作为助手再次检查逻辑。编码愉快!

编辑:由于您询问的 case 树中没有特别复杂的东西,我想这个应该可以完成工作:

_seuss()
{
    case  in
        seuss)      COMPREPLY=($(compgen -W "fox tweedle" -- ""))     ;;
        fox)        COMPREPLY=($(compgen -W "socks" -- ""))           ;;
        socks)      COMPREPLY=($(compgen -W "box clocks" -- ""))      ;;
        box)        COMPREPLY=($(compgen -W "knox" -- ""))            ;;
        tweedle)    COMPREPLY=($(compgen -W "beetle poodle" -- ""))   ;;
        beetle)     COMPREPLY=($(compgen -W "puddle battle" -- ""))   ;;
        poddle)     COMPREPLY=($(compgen -W "noodle" -- ""))          ;;
        *)          COMPREPLY=()                                        ;;
    esac
}

complete -F _seuss seuss

这里</code>表示当前单词正在完成,<code>是前一个单词。