I have the following completion script to complete a list of roles:

host /usr/share/zsh/vendor-completions # cat _foo
#compdef foo

local -a values=('ROLE_ADMIN[Admin]' 'ROLE_USER[User]')

_values -s , 'roles' $values

This works fine so far; it'll complete the roles:

host ~ # foo ROLE_<TAB>
ROLE_ADMIN  -- Admin
ROLE_USER   -- User

But I want the completion to work case-insensitively, ie. if I type now type ad after ROLE_, I want it to complete ROLE_ADMIN, which doesn't work.

I've figured out that I need to use compadd -M with a match-spec like 'm:{[:lower:]}={[:upper:]}', but I can't figure out how to pass this to _values which doesn't seem to support -M.

1 Answer 1


_values indeed can't do this, but the problem is easily circumvented by replacing _values with _sequence _describe to get the value completion manually, and _describe does support the -M option:

host /usr/share/zsh/vendor-completions # cat _foo2
#compdef foo2

local -a values=('ROLE_ADMIN:Admin' 'ROLE_USER:User')

_sequence _describe 'roles' values -M 'm:{[:lower:]}={[:upper:]}'

Note that _describe requires the descriptions in a slightly different format - word:desc instead of word[desc].

Now it'll complete case-insensitively as expected:

host ~ # foo2 ROLE_ad<TAB>
host ~ # foo2 ROLE_ADMIN,
  • Big thanks to llua who actually came up with this solution when I asked for help in the #zsh IRC channel with this. Aug 21, 2021 at 14:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .