自动完成 bash 与 zsh

autocomplete bash vs. zsh

我确实有一个简单的功能(在“现实”中它“有点”复杂 - 仅供说明)

cat test.sh
_foocomplete(){
        local list="abc\ndef\nghi"
        local cur=${COMP_WORDS[COMP_CWORD]}
        COMPREPLY=( $(echo -e ${list} | grep "${cur}") )
}

foo(){
        echo ""
}

complete -F _foocomplete foo

在 bash 中使用这个给了我

~ ❯ ps -o cmd= $$
bash
~ ❯ type foo
bash: type: foo: not found
~ ❯ source test.sh
~ ❯ foo <TAB>
abc  def  ghi
~ ❯ foo a<TAB>
abc
~ ❯ foo e<TAB>
def

在zsh中使用,非常相似

~ ❯ ps -o cmd= $$
-zsh
~ ❯ type -f foo
foo not found
~ ❯ source test.sh
~ ❯ foo <TAB>
abc  def  ghi
~ ❯ foo a<TAB>
abc

但是那个

~ ❯ foo e<TAB>

不起作用(如:不起作用,如 bash,给我 def 作为选项)。

除了重写和使用 compdef 之外,是否有“简单”的解释(和“修复”)?

这没有 .zshrc(但也有 Oh My Zsh)

作为对

的回复
cat test2.sh
foo(){
        local list="abc\ndef\nghi"
        echo -e ${list} | grep e
}

foo
~ ❯ /bin/zsh test2.sh
def
~ ❯ /bin/bash test2.sh
def

提前致谢

Zsh 补全会自己“匹配”,而 bash 希望您使用例如grep。 “def”不以“e”开头,所以默认不补全。您可以将默认匹配视为将 * 放在光标位置。

我假设您必须为该示例使用 bashcompinit 才能接近在 zsh 中工作。不幸的是,这意味着通常用于配置 zsh 完成的钩子不可用。 bashcompinit 使 zsh 的默认匹配处于活动状态,正如您观察到的那样,它的行为方式与 bash 不完全相同 - 通过使用 compadd 的 -U 选项,它可以做到这一点。 Zsh 的匹配通常可以用 matchermatcher=list 样式来控制。将 -M 传递给 compadd 也有效。以下是类似于您的 bash 示例的基本本机 zsh 完成:

    _foo() { compadd -M 'l:|=*' abc def ghi }
    compdef _foo foo