4

I have a zsh auto completion function for a command called gd which does a fuzzy search based on the $words[CURRENT] value and return suggestions. The search is working fine but zsh does not show any candidates because the entered text is not a prefix of the suggestion.

e.g.

% gd hw

Might generate the completion oh hello there, world

But zsh won't show that because hw is not found at the start of the suggestion.

Can I make zsh offer the suggestion as something that would replace the current word when chosen?

Here's a simplified version of my completion script in a file called _gd which is in my fpath:

#compdef gd

_gd() {
  local -a list

  clue="$words[CURRENT]"

      pattern=""
      for i in $(seq $#clue)
      do
        pattern="$pattern.*${clue[i]}"
      done
      while read dir
      do
        list=( $list $dir )
      done <<<$(grep "$pattern" ~/.recent-dirs)

  _describe gd list
}

2 Answers 2

2

Get rid of that _gd function and just add the following to your .zshrc file:

autoload -Uz compinit
compinit
zstyle ':completion:*' matcher-list 'r:|?=**'

This tells the completion code to allow any number of additional between and around what you’ve types. With this, Zsh can now fuzzy complete anything.

  • r:X|Y=Z looks for all non-overlapping substrings that match pattern XY and makes it so the part matched by X also matches anything matched by pattern Z when checking for matching completions.
  • ? matches any one character.
  • If X or Y equals *, it matches any number of consecutive characters.
  • If Z equals *, it matches any number of consecutive characters except anything matched by Y.
  • If Z equals **, it matches any number of consecutive characters.
  • In r:|?=**, X equals the empty string.
  • By default, Zsh already adds a wildcard to the end of your input, thus completing the circle for full fuzzy matching.

You can find the documentation over here: http://zsh.sourceforge.net/Doc/Release/Completion-Widgets.html#Completion-Matching-Control

4
  • Awesome, thanks, that's made it simpler. Wonder what that 'r:|?=**' does?! Commented May 20, 2020 at 19:53
  • 1
    I updated my answer with a bit more info. Here’s the documentation, if you’re interested: zsh.sourceforge.net/Doc/Release/… Commented May 20, 2020 at 21:31
  • Hi Marlon, follow up question at unix.stackexchange.com/questions/590472/… if you're interested! Commented Jun 2, 2020 at 17:02
  • @MarlonRichert This is cool, but I couldn't make it work for my related problem: stackoverflow.com/questions/69331610/… If I'm reading your answer right, setting the zstyle as you do should allow a function to complete fo<TAB> to blah should work, but no dice in my experiments. Do you know why this trick isn't working? Commented Sep 26, 2021 at 12:23
0

This is hack while I wait on more wise answers...

What I've done is made my suggestion generator produce suggestions like:

hw»oh hello there, world

Because the command (actually a function) is in my control, I simply strip off the rubbish at the start:

input="${input#*»}"

But it would be nice to know how to do it properly.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.