The default ShellCompDirective can be configured

This commit is contained in:
Harald Albers 2025-01-19 22:32:32 +00:00
parent 01ffff4eca
commit 440c33b3b3
3 changed files with 69 additions and 1 deletions

View file

@ -115,6 +115,9 @@ type CompletionOptions struct {
DisableDescriptions bool
// HiddenDefaultCmd makes the default 'completion' command hidden
HiddenDefaultCmd bool
// DefaultShellCompDirective sets the ShellCompDirective that is returned
// if no special directive can be determined
DefaultShellCompDirective ShellCompDirective
}
// NoFileCompletions can be used to disable file completion for commands that should
@ -451,7 +454,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
return finalCmd, completions, directive, nil
}
} else {
directive = ShellCompDirectiveDefault
directive = finalCmd.CompletionOptions.DefaultShellCompDirective
if flag == nil {
foundLocalNonPersistentFlag := false
// If TraverseChildren is true on the root command we don't check for

View file

@ -3742,3 +3742,45 @@ func TestDisableDescriptions(t *testing.T) {
})
}
}
func TestCustomDefaultShellCompDirective(t *testing.T) {
rootCmd := &Command{Use: "root", Run: emptyRun}
rootCmd.Flags().String("string", "", "test string flag")
// use ShellCompDirectiveNoFileComp instead of the default, which is ShellCompDirectiveDefault
rootCmd.CompletionOptions.DefaultShellCompDirective = ShellCompDirectiveNoFileComp
testCases := []struct {
desc string
args []string
}{
{
"args completion with custom ShellCompDirective",
[]string{""},
},
{
"flag completion with custom ShellCompDirective",
[]string{"--string", ""},
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
args := []string{ShellCompNoDescRequestCmd}
args = append(args, tc.args...)
output, err := executeCommand(rootCmd, args...)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := strings.Join([]string{
":4",
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
})
}
}

View file

@ -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.
#### Debugging
You can also easily debug your Go completion code for flags: