bash 补全仅适用于第一个非选项词?

bash 补全仅适用于第一个非选项词?

我有一个程序,foo就像许多其他程序一样,它采用以下形式的命令行参数:

foo[选项]命令...

在哪里选项是零个或多个短(例如,-s)或长(例如,--long)样式选项,后跟正好一个命令关键字后跟该命令的参数。

我想要一个 Bash 完成功能,可以完成长选项或命令。方便地,foo还采用--options打印其选项列表和--commands打印其命令列表的选项。

我希望该功能能够提供建议仅有的对于第一个非选项词(命令) 在命令行上并提供键入时对后续单词的建议tab

使用部分这个答案,我尝试COMP_CWORD仅在其值为 1 时使用并执行补全。这是到目前为止我的补全函数:

_foo() {
  local cur=${COMP_WORDS[COMP_CWORD]}

  if [[ "$cur" == -* ]]
  then COMPREPLY=($(compgen -W "$(foo --options)" -- $cur))
  else
    if (( COMP_CWORD == 1 ))
    then COMPREPLY=($(compgen -W "$(foo --commands)" -- $cur))
    else COMPREPLY=()
    fi
  fi
}

几乎作品。但是,如果用户在命令喜欢:

foo --long tab

然后tab,外壳发出蜂鸣声。我认为这是因为COMP_CWORD此时为 2,因为它不区分选项和非选项。

好的,那么我想让该函数扫描当前单词之前的所有单词,并减去以-这样的开头的单词数:

_foo() {
  local cur=${COMP_WORDS[COMP_CWORD]}

  if [[ "$cur" == -* ]]
  then
    COMPREPLY=($(compgen -W "$(foo --options)" -- $cur))
  else
    local i=$COMP_CWORD
    while (( i > 1 ))
    do
      [[ "${COMP_WORDS[i-1]}" != -* ]] && break
      ((--i))
    done
    if (( i == 1 ))
    then COMPREPLY=($(compgen -W "$(foo --commands)" -- $cur))
    else COMPREPLY=()
    fi
  fi
}

这是可行的,但问题是,如果用户给出一个简短的选项,该选项接受一个参数并提供所述参数作为下一个单词,例如:

foo -s arg tab

那么索引就会减一。完成函数必须详细了解所有选项,无论它们是否带有参数,并且必须有效地解析所有选项以获得正确的索引。

这看起来工作量很大。有没有更简单的方法让我的补全功能只为第一个非选项词提供建议?或者只是放弃并总是提供建议?

相关内容