Skip to content

Commit 212ea40

Browse files
authored
Include --help and --version flag in completion (#1813)
Fixes #1786 The --help, -h, --version and -v flags are normally added when the `execute()` function is called on a command. When doing completion we don't call `execute()` so we need to add these flags explicitly to the command being completed. Also, we disable all further completions if the 'help' or 'version' flags are present on the command-line. Signed-off-by: Marc Khouzam <[email protected]>
1 parent d4040ad commit 212ea40

File tree

3 files changed

+257
-5
lines changed

3 files changed

+257
-5
lines changed

command.go

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
flag "github.com/spf13/pflag"
3131
)
3232

33+
const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
34+
3335
// FParseErrWhitelist configures Flag parse errors to be ignored
3436
type FParseErrWhitelist flag.ParseErrorsWhitelist
3537

@@ -1064,6 +1066,7 @@ func (c *Command) InitDefaultHelpFlag() {
10641066
usage += c.Name()
10651067
}
10661068
c.Flags().BoolP("help", "h", false, usage)
1069+
_ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"})
10671070
}
10681071
}
10691072

@@ -1089,6 +1092,7 @@ func (c *Command) InitDefaultVersionFlag() {
10891092
} else {
10901093
c.Flags().Bool("version", false, usage)
10911094
}
1095+
_ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"})
10921096
}
10931097
}
10941098

completions.go

+24
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
274274
}
275275
finalCmd.ctx = c.ctx
276276

277+
// These flags are normally added when `execute()` is called on `finalCmd`,
278+
// however, when doing completion, we don't call `finalCmd.execute()`.
279+
// Let's add the --help and --version flag ourselves.
280+
finalCmd.InitDefaultHelpFlag()
281+
finalCmd.InitDefaultVersionFlag()
282+
277283
// Check if we are doing flag value completion before parsing the flags.
278284
// This is important because if we are completing a flag value, we need to also
279285
// remove the flag name argument from the list of finalArgs or else the parsing
@@ -306,6 +312,12 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
306312
}
307313
}
308314

315+
// Look for the --help or --version flags. If they are present,
316+
// there should be no further completions.
317+
if helpOrVersionFlagPresent(finalCmd) {
318+
return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil
319+
}
320+
309321
// We only remove the flags from the arguments if DisableFlagParsing is not set.
310322
// This is important for commands which have requested to do their own flag completion.
311323
if !finalCmd.DisableFlagParsing {
@@ -477,6 +489,18 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
477489
return finalCmd, completions, directive, nil
478490
}
479491

492+
func helpOrVersionFlagPresent(cmd *Command) bool {
493+
if versionFlag := cmd.Flags().Lookup("version"); versionFlag != nil &&
494+
len(versionFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && versionFlag.Changed {
495+
return true
496+
}
497+
if helpFlag := cmd.Flags().Lookup("help"); helpFlag != nil &&
498+
len(helpFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && helpFlag.Changed {
499+
return true
500+
}
501+
return false
502+
}
503+
480504
func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
481505
if nonCompletableFlag(flag) {
482506
return []string{}

0 commit comments

Comments
 (0)