嵌套bash自动补全脚本 [英] Nested bash autocompletion script

查看:74
本文介绍了嵌套bash自动补全脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试向最近使用的命令行程序添加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 subcommands version, process, and help. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆