Open raphaelvigee opened 2 years ago
Hi @raphaelvigee. Fuzzy matching is already possible for ValidArgsFunction
and RegisterFlagCompletionFunc
. All that is required is for you not to filter on prefix. Helm does this for example: https://github.com/helm/helm/pull/10513.
However, this only works for zsh
and fish
. I was under the impression that bash
did not handle fuzzy matching so the Cobra bash script does not allow it. Could you give an example where you say bash
support fuzzy matching?
Finally, for completeness, be aware Cobra does filter on the prefix when it does completion itself. For instance, when completion subcommands and flag names. I have been hesitant to change that as I am not convinced it is a common scenario.
I can confirm that fuzzy matching does not work on zsh, the situation highlighted above returns no completion in the terminal as they get filtered out in _describe
(which follows the user-defined matchers), but i think the CLI author should be able to say "you defo want fuzzy matching here", hence passing the extra directive.
Debugging it, i can see the completion up until it passes through _describe
.
From the zsh debug:
+_mycmd:68> __mycmd_debug $'completions: some_arg\nsome_arg_thats_long'
...
+_mycmd:160> __mycmd_debug 'Calling _describe'
...
+_mycmd:167> __mycmd_debug '_describe did not find completions.'
A similar thing is happening with bash
I don't have an example in mind that does fuzzy matching, but for my current use-case, fuzzy matching is almost necessary, basically: mycmd
takes a single argument which is a list of urls, these urls are long and complicated, and fuzzy matching would make the user life much easier
For fuzzy matching to work for zsh
you need to set the matcher-list
in zstyle
. I get this automatically with oh-my-zsh
.
$ zstyle | grep -A1 matcher-list
matcher-list
:completion:* 'm:{a-zA-Z-_}={A-Za-z_-}' 'r:|=*' 'l:|=* r:|=*'
You can try it by running:
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'
This article explains it well: https://thevaluable.dev/zsh-completion-guide-examples/
As for bash
, I don't know if it supports this kind of matching. I believe it does not and only matches on prefix
I do have this matcher in:
$ zstyle | grep -A1 matcher-list
matcher-list
:completion:* 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'
But i feel like we should be able to make the matching handled by cobra user-code and not whatever shell I am using.
One may decide to do fuzzy matching, or more advanced things (for example when matching a path, one could decide to do some advanced fuzzy matching by path parts, splitting by /
and matching the individual units)
I do have this matcher in:
I would expect your example to work with zsh in that case.
But i feel like we should be able to make the matching handled by cobra user-code and not whatever shell I am using.
That would be great. I'm just not aware if you can get the different shells to do what you want.
I would expect your example to work with zsh in that case.
Same, but zsh does not seem to agree as per the logs in https://github.com/spf13/cobra/issues/1828#issuecomment-1283110025
That would be great. I'm just not aware if you can get the different shells to do what you want.
Well it would be best effort, if some shell doesn't support it, so be it, prefix matching it is!
Same, but zsh does not seem to agree as per the logs in #1828 (comment)
In case it helps, you can at least verify what Cobra sends the shell as completion choices like this: mycmd __complete arg<ENTER>
Well it would be best effort, if some shell doesn't support it, so be it, prefix matching it is!
That's kind of what Cobra does now. If the program returns completion choices that are not filtered on prefix, then zsh and fish will do fuzzy matching if the user has configured the shell to do it.
In case it helps, you can at least verify what Cobra sends the shell as completion choices like this: mycmd __complete arg
Cobra returns the right value +_mycmd:68> __mycmd_debug $'completions: some_arg\nsome_arg_thats_long'
That's kind of what Cobra does now. If the program returns completion choices that are not filtered on prefix, then zsh and fish will do fuzzy matching if the user has configured the shell to do it.
Well yes and no, it does relies on the user having the right matchers configured (and zsh behaving correctly)
To try and move this forward, would it be acceptable to add a new directive to bypass the shell matching altogether ?
To try and move this forward, would it be acceptable to add a new directive to bypass the shell matching altogether ?
If the final solution is more flexible than what we have now and that the way to use this new solution is user-friendly, then yes, no problem adding a new directive. PR welcome.
The Cobra project currently lacks enough contributors to adequately respond to all issues. This bot triages issues and PRs according to the following rules:
This would allow to support fuzzy completions: Lets say
ValidArgsFunction
return[]string{"some_arg", "some_arg_thats_long"}
I should be presented with the autocomplete options:
Currently those would be filtered out because of the use of
compgen
on bash and_describe
on zsh (haven't checked fish) those will be filtered out as the default behavior is to filter based on prefix.The addition of another directive
ShellCompDirectiveNoMatching
(something like that) would disable the matching