-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
The default ShellCompDirective can be configured #2221
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -304,6 +304,29 @@ $ helm status --output [tab][tab] | |
json table yaml | ||
``` | ||
|
||
#### Change the default ShellCompDirective | ||
|
||
If Cobra cannot determine a special `ShellCompDirective` during flag parsing, | ||
it will return `ShellCompDirectiveDefault`, which will invoke the shell's filename completion. | ||
This is handy for flags that accept filenames, as they do not require a `FlagCompletionFunc`. | ||
|
||
For other flags where no meaningful completion can be provided, this requires extra work: | ||
You have to register a `FlagCompletionFunc` just to get rid of file completion. | ||
|
||
If you find yourself registering lots of handlers like | ||
|
||
```go | ||
cmd.RegisterFlagCompletionFunc("flag-name", cobra.NoFileCompletions) | ||
``` | ||
|
||
you can change the default `ShellCompDirective` to `ShellCompDirectiveNoFileComp`: | ||
|
||
```go | ||
cmd.CompletionOptions.DefaultShellCompDirective = ShellCompDirectiveNoFileComp | ||
``` | ||
|
||
Keep in mind that from now on you have to register handlers for every filename flag. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do think of the slightly reworked: #### Change the default ShellCompDirective When no completion function is registered for a leaf command or for a flag, Cobra will automatically use `ShellCompDirectiveDefault`, which will invoke the shell's filename completion. This implies that when file completion does not apply to a leaf command or to a flag (the command or flag does not operate on a filename), turning off file completion requires you to register a completion function for that command/flag. For example: ```go cmd.RegisterFlagCompletionFunc("flag-name", cobra.NoFileCompletions) ``` If you find that there are more situations where file completion should be turned off than when it is applicable, you can change the default `ShellCompDirective` to `ShellCompDirectiveNoFileComp`: ```go rootCmd.CompletionOptions.DefaultShellCompDirective = ShellCompDirectiveNoFileComp ``` If doing so, keep in mind that you should instead register a completion function for leaf commands or flags where file completion is applicable. For example: ```go cmd.RegisterFlagCompletionFunc("flag-name", cobra.FixedCompletions(nil, ShellCompDirectiveDefault)) ``` There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is much better than my version, thank you very much. |
||
#### Debugging | ||
|
||
You can also easily debug your Go completion code for flags: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to settle on what would be the best API for this new option.
Where do we expect the developer to set
CompletionOptions.DefaultShellCompDirective
?You've implemented option 2, and I wanted to ask if this was a conscious decision?
Whatever we settle on, I suggest making it clear on the comment above the definition of the new option, and also in the documenation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marckhouzam
It was a conscious decision.
Changing the default
ShellCompDirective
has massive side effects (effectively inverting the logic when and when not to write boilerplate handlers). I prefer an explicit opt-in for this change on the command level that does not propagate to child commands. This allows gradually introducing this new setting in just the places where it makes sense.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You make a good point. But I can't help imagining a developer trying to use this option and being annoyed at having to set it on every single command; some programs have quite a lot of them; I feel like someone will come back and ask for another option to set a "global" default directive 😄 .
If we implement option 3 (affect command and its sub-commands), and a dev only wants to set the option for a single command, they could achieve this by setting the option on the specific command, and then setting the option to ShellCompDirectiveDefault on the first level children of that command. How awkward would that seem to you as an API?
I want to get this as best we can because once it is released, we will not be able to change it (except by introducing another completion option).
@thaJeztah Feel free to give your opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ccoVeille If you have an opinion, don't hesitate.
Or anyone else for that matter 😄
This is a community project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the root command should propagate it, but then:
if someone comes and say "hey, you should set this at root level dude", then some commands may be broken because they expect to have file completion, which is the default one, and it will be broken.
Most CLIs are never tested, first because it's not that easy, then because people are lazy or dislike tests.
So here choosing among the options is more about mitigating the consequences of each of them, and choose the one with the least consequences.
I prefer boilerplate and people having to add a directive on each command than having magical things that will hide problem, because things would be "magical"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For existing codebases, the second option seems to be most suitable for me because the others are too dangerous, or at least might violate the principle of least surprise.
For new projects, an approch with inheritance is probably a better choice. As a compromise, for those projects I would recommend the third option. It is also more flexible that option one, which assumes that all commands have the same file option density.
The choice depends on how much we weigh each of these use cases.