1

I do have a simple function (in "reality" it is "a bit" more complex - just for illustration)

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

foo(){
        echo "$1"
}

complete -F _foocomplete foo

Using this in bash, gives me

~ ❯ 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

Using it in zsh, is very similar

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

BUT that

~ ❯ foo e<TAB>

does not work (as in: does not, like in bash, give me def as option).

Is there - besides rewriting and using compdef - an "easy" explanation (and "fix")?

This is with no .zshrc (but also with e.g. Oh My Zsh)

As reply to autocomplete bash vs. 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

Thank you in advance

  • `local list="abc\ndef\nghi"` and `echo -e ${list}` - that's strange. Please test such code in both zsh and bash. – KamilCuk Nov 02 '20 at 22:25
  • Please don't add comments to clarify, code is unreadable in comments. [Edit] your question instead. – Robert Nov 02 '20 at 22:50
  • `printf '%b\n' "$list"` is more reliable and portable than `echo -e "$list"`, and **much** less buggy than `echo -e $list`. See [Why is printf better than echo?](https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo) on [unix.se], and [I just assigned a variable, but `echo $variable` prints something else!](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) here. – Charles Duffy Nov 02 '20 at 23:05

1 Answers1

1

Zsh completion does "matching" itself while bash expects you to filter completion candidates with, e.g. grep. "def" does not begin with "e" so it is not completed by default. You can think of the default matching as putting * at just the cursor position.

I assume you must be using bashcompinit for that example to have even come close to working in zsh. Unfortunately that means that the usual hooks for configuring zsh completions are not available. bashcompinit leaves zsh's default matching active which as you observe makes it not behave in exactly the same way as bash - by using compadd's -U option it could have done that. Zsh's matching can usually be controlled with the matcher and matcher=list styles. Passing -M to compadd also works. The following is a basic native zsh completion similar to your bash example:

    _foo() { compadd -M 'l:|=*' abc def ghi }
    compdef _foo foo
okapi
  • 1,340
  • 9
  • 17