Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to bypass the terminal autocomplete matching #1828

Open
raphaelvigee opened this issue Oct 13, 2022 · 10 comments
Open

Add a way to bypass the terminal autocomplete matching #1828

raphaelvigee opened this issue Oct 13, 2022 · 10 comments
Labels
area/shell-completion All shell completions

Comments

@raphaelvigee
Copy link

This would allow to support fuzzy completions:
Lets say ValidArgsFunction return []string{"some_arg", "some_arg_thats_long"}

$ mycmd arg<TAB>

I should be presented with the autocomplete options:

some_arg
some_arg_thats_long

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

@marckhouzam
Copy link
Collaborator

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: helm/helm#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.

@raphaelvigee
Copy link
Author

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

@marckhouzam
Copy link
Collaborator

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

@raphaelvigee
Copy link
Author

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)

@marckhouzam
Copy link
Collaborator

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.

@raphaelvigee
Copy link
Author

raphaelvigee commented Oct 19, 2022

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 #1828 (comment)

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!

@marckhouzam
Copy link
Collaborator

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.

@raphaelvigee
Copy link
Author

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 ?

@marckhouzam
Copy link
Collaborator

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.

@github-actions
Copy link

The Cobra project currently lacks enough contributors to adequately respond to all issues. This bot triages issues and PRs according to the following rules:

  • After 60d of inactivity, lifecycle/stale is applied. - After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied and the issue is closed.
    You can:
  • Make a comment to remove the stale label and show your support. The 60 days reset. - If an issue has lifecycle/rotten and is closed, comment and ask maintainers if they'd be interested in reopening

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/shell-completion All shell completions
Projects
None yet
Development

No branches or pull requests

3 participants