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.


_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 '21 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.