在 bash 中是否可以完成一个单词的中间?

在 bash 中是否可以完成一个单词的中间?

我有一个简单的 bash 完成脚本,用于我的自定义 git 分支搜索器。

#/usr/bin/env bash
_branch_completions()
{
  local word="${COMP_WORDS[COMP_CWORD]}";
  if [ ! -z "$word" ]
  then
    COMPREPLY=($(compgen -W "`git branch | grep $word`" "${COMP_WORDS[1]}"))
  fi
}

complete -F _branch_completions branch

“分支”脚本在分支内搜索,这样我就可以搜索

branch 5.9

我会得到

1 release/5.9.0
2 hotfix/5.9.1
3 hotfix/5.9.2
Please select a branch

我的 bash 完成脚本将完成分支 reletabtab 并给我 release/5.9.0,但我希望能够执行分支 5.9tabtab并获取所有这些

答案1

来自bash 手册页

compgen [option] [word]
...
    If word is specified, only those completions matching word will be displayed.

您已经使用 grep 过滤了列表,因此为了获得所需的行为,您可以简单地省略 compgen 的第二个参数,从而使您的行:

COMPREPLY=($(compgen -W "`git branch | grep $word`"))

答案2

Necropost,但值得进一步提及的是:即使没有 compgen,readline lib 本身在涉及模糊匹配和常见前缀时也可能会造成一些混乱:

function _bash_completion_smth() {
        COMPREPLY=(1aaa2 2aaa3 3bbb4)
}
$ complete -F _bash_completion_smth smth
$ smth[TAB][TAB]
1aaa2 2aaa3 3bbb4
$ smth aaa[TAB][TAB]
1aaa2 2aaa3 3bbb4
$ # word 3bbb4 is undesired

这些方面由 readline lib 的变量控制

show-all-if-ambiguous(关闭)
这将改变补全功能的默认行为。如果设置为开启,则具有多个可能补全的单词将立即列出匹配项,而不是响铃。

show-all-if-unmodified(关闭)
这将改变补全功能的默认行为,其方式类似于 show-all-if-ambiguous。如果设置为开启,则具有多个可能补全而没有任何可能的部分补全(可能的补全不共享公共前缀)的单词将立即列出匹配项,而不是响铃。

可以直接在完成函数中调整 Readline lib 的变量 bind "set variable value"

此处解释了这两个变量的详细信息如果有歧义则显示全部 vs 如果未修改则显示全部

相关内容