feat(completion): add default completion hidden if there are no subcommands

The default completion is useful also in cases where there are no
subcommands, for example to provide completion for flags, and custom
completions for their values.

But when there are no subcommands, make it hidden. Simply adding it
non-hidden would result in a help section to be added just for it which
is just noise: the completion command is not the primary functionality
of the program, yet it would be prominently displayed in help output. It
would also get included among argument completions, which could be a
source of confusion.
This commit is contained in:
Ville Skyttä 2021-07-10 12:03:08 +03:00
parent 19c9c74384
commit c7cee2aba3
3 changed files with 15 additions and 6 deletions

View file

@ -586,7 +586,7 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p
// 2- c has no subcommands (to avoid creating one), // 2- c has no subcommands (to avoid creating one),
// 3- c already has a 'completion' command provided by the program. // 3- c already has a 'completion' command provided by the program.
func (c *Command) initDefaultCompletionCmd() { func (c *Command) initDefaultCompletionCmd() {
if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() { if c.CompletionOptions.DisableDefaultCmd {
return return
} }
@ -598,6 +598,7 @@ func (c *Command) initDefaultCompletionCmd() {
} }
haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions
hidden := c.CompletionOptions.HiddenDefaultCmd || !c.HasSubCommands()
completionCmd := &Command{ completionCmd := &Command{
Use: compCmdName, Use: compCmdName,
@ -607,7 +608,7 @@ See each sub-command's help for details on how to use the generated script.
`, c.Root().Name()), `, c.Root().Name()),
Args: NoArgs, Args: NoArgs,
ValidArgsFunction: NoFileCompletions, ValidArgsFunction: NoFileCompletions,
Hidden: c.CompletionOptions.HiddenDefaultCmd, Hidden: hidden,
} }
c.AddCommand(completionCmd) c.AddCommand(completionCmd)

View file

@ -2287,14 +2287,21 @@ func TestDefaultCompletionCmd(t *testing.T) {
Run: emptyRun, Run: emptyRun,
} }
// Test that no completion command is created if there are not other sub-commands // Test that default completion command is created, hidden if there are no other sub-commands
assertNoErr(t, rootCmd.Execute()) assertNoErr(t, rootCmd.Execute())
found := false
for _, cmd := range rootCmd.commands { for _, cmd := range rootCmd.commands {
if cmd.Name() == compCmdName { if cmd.Name() == compCmdName {
t.Errorf("Should not have a 'completion' command when there are no other sub-commands of root") found = true
if !cmd.Hidden {
t.Errorf("The 'completion' command should be hidden when there are no other sub-commands of root")
}
break break
} }
} }
if !found {
t.Errorf("Should have a 'completion' command when there are no other sub-commands of root")
}
subCmd := &Command{ subCmd := &Command{
Use: "sub", Use: "sub",
@ -2303,7 +2310,7 @@ func TestDefaultCompletionCmd(t *testing.T) {
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
// Test that a completion command is created if there are other sub-commands // Test that a completion command is created if there are other sub-commands
found := false found = false
assertNoErr(t, rootCmd.Execute()) assertNoErr(t, rootCmd.Execute())
for _, cmd := range rootCmd.commands { for _, cmd := range rootCmd.commands {
if cmd.Name() == compCmdName { if cmd.Name() == compCmdName {

View file

@ -8,7 +8,8 @@ The currently supported shells are:
- PowerShell - PowerShell
Cobra will automatically provide your program with a fully functional `completion` command, Cobra will automatically provide your program with a fully functional `completion` command,
similarly to how it provides the `help` command. similarly to how it provides the `help` command. If there are no other subcommands, the
default `completion` command will be hidden, but still functional.
## Creating your own completion command ## Creating your own completion command