Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I configure zsh for completion of partial words, but case-insensitive?

Currently I have this in my ~/.zshrc:

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'

AFAIU 'm:{a-z}={A-Za-z}' means that I will get case-insensitive tab completion, e.g. foo will tab-complete to Foobar (if that exists). And 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' means that I will get matches for later parts of a word, e.g. bar will tab-complete to foobar (if that exists). But those partial matches are not case-insensitive. So for example bar will not tab-complete to FooBar (again, in case that exists).

Is there a way to get that working?

like image 262
shahn Avatar asked Oct 25 '25 09:10

shahn


1 Answers

The lists of matchers (each string containing one or more matchers) in your matcher-list are always tried one at a time, until one of them returns at least one match. By default, each list of matchers completely replaces the previous one. To instead make the next matcher list include the previous one, you need to prefix it with a +:

zstyle ':completion:*' matcher-list \
    'm:{[:lower:]}={[:upper:]}' \
    '+r:|[._-]=* r:|=*' \
    '+l:|=*'

See the matcher-list completion style doc.


And 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' means that I will get matches for later parts of a word, e.g. bar will tab-complete to foobar (if that exists).

Not exactly:

  • If <word> is the string on the command line that’s being completed, then,
    • by default, Zsh will return completions matching the glob pattern <word>*, — except when COMPLETE_IN_WORD is set, which case it will create a completion pattern by inserting the * at the cursor position instead.
  • r:|<pattern>=* means “In <word>,
    • for each occurrence of the empty string (since there's nothing between : and |)
    • that is followed to the right (r) by something matching <pattern>,
    • insert a * in the completion pattern between the two.”
  • [._-] is a pattern that matches a single instance of ., _ or -.
  • r:|=* (without anything to the right of |) means
    • “If <word> ends on the right with an empty string (which is always true),
    • then insert a * in that position in the completion pattern.”
  • l:|=* (without anything to the left of |) means
    • “If <word> starts on the left with an empty string (always true),
    • then insert a * in that position in the completion pattern.”
  • Matchers inside each matcher list are applied in the order they are listed. This is important, as changing their order might change the resulting completion pattern.

See the completion matching control docs for a more in-depth explanation.

like image 112
Marlon Richert Avatar answered Oct 28 '25 04:10

Marlon Richert