2012-02-18 134 views
1

我一直在尝试将bash完成支持添加到我最近使用的命令行程序中,但似乎我已经撞上了墙。嵌套的bash自动完成脚本

下面是我想自动完成

  • 主要命令是foo的命令和子命令,自动完成应为子versionprocesshelp进行。进一步的自动完成取决于子命令。

    • 如果用户在主指令后进入-,自动完成执行用于这些词完成:--activate--deactivate

    • 如果用户输入--deactivate,它应该执行一个bash命令输出的自动完成(比方说ls)。

  • version:没有自动完成执行
  • process:自动完成默认为列出目录(当前的和包括在父)

    • 如果用户输入-,自动完成对这些词进行完成:--color--verbose然后停止
  • 如果用户输入help,则自动完成适用于其他子命令(processversion)。

这是我目前实施的自动完成脚本(这是严重不及格):

_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函数,但目前我不知道该怎么做。如果你对如何实现这一点也有建议,我会很感激。

谢谢!

回答

3

在第一级可能的子命令的情况下,我有点不清楚。 是否可以输入foo --activatefoo - --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) 
    ...