Don't complete --help flag when flag parsing disabled (#2061)
Fixes #2060 When a command sets `DisableFlagParsing = true` it requests the responsibility of doing all the flag parsing. Therefore even the `--help/-f/--version/-v` flags should not be automatically completed by Cobra in such a case. Without this change the `--help/-h/--version/-v` flags can end up being completed twice for plugins: one time from cobra and one time from the plugin (which has set `DisableFlagParsing = true`). Signed-off-by: Marc Khouzam <marc.khouzam@gmail.com>
This commit is contained in:
parent
8b1eba4761
commit
b711e8760b
@ -302,9 +302,13 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||||||
|
|
||||||
// These flags are normally added when `execute()` is called on `finalCmd`,
|
// These flags are normally added when `execute()` is called on `finalCmd`,
|
||||||
// however, when doing completion, we don't call `finalCmd.execute()`.
|
// however, when doing completion, we don't call `finalCmd.execute()`.
|
||||||
// Let's add the --help and --version flag ourselves.
|
// Let's add the --help and --version flag ourselves but only if the finalCmd
|
||||||
|
// has not disabled flag parsing; if flag parsing is disabled, it is up to the
|
||||||
|
// finalCmd itself to handle the completion of *all* flags.
|
||||||
|
if !finalCmd.DisableFlagParsing {
|
||||||
finalCmd.InitDefaultHelpFlag()
|
finalCmd.InitDefaultHelpFlag()
|
||||||
finalCmd.InitDefaultVersionFlag()
|
finalCmd.InitDefaultVersionFlag()
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we are doing flag value completion before parsing the flags.
|
// Check if we are doing flag value completion before parsing the flags.
|
||||||
// This is important because if we are completing a flag value, we need to also
|
// This is important because if we are completing a flag value, we need to also
|
||||||
@ -408,6 +412,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||||||
finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
doCompleteFlags(flag)
|
doCompleteFlags(flag)
|
||||||
})
|
})
|
||||||
|
// Try to complete non-inherited flags even if DisableFlagParsing==true.
|
||||||
|
// This allows programs to tell Cobra about flags for completion even
|
||||||
|
// if the actual parsing of flags is not done by Cobra.
|
||||||
|
// For instance, Helm uses this to provide flag name completion for
|
||||||
|
// some of its plugins.
|
||||||
finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
doCompleteFlags(flag)
|
doCompleteFlags(flag)
|
||||||
})
|
})
|
||||||
|
@ -2622,8 +2622,6 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) {
|
|||||||
expected := strings.Join([]string{
|
expected := strings.Join([]string{
|
||||||
"--persistent",
|
"--persistent",
|
||||||
"-p",
|
"-p",
|
||||||
"--help",
|
|
||||||
"-h",
|
|
||||||
"--nonPersistent",
|
"--nonPersistent",
|
||||||
"-n",
|
"-n",
|
||||||
"--flag",
|
"--flag",
|
||||||
@ -3053,8 +3051,26 @@ func TestCompletionCobraFlags(t *testing.T) {
|
|||||||
return []string{"extra3"}, ShellCompDirectiveNoFileComp
|
return []string{"extra3"}, ShellCompDirectiveNoFileComp
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
childCmd4 := &Command{
|
||||||
|
Use: "child4",
|
||||||
|
Version: "1.1.1",
|
||||||
|
Run: emptyRun,
|
||||||
|
ValidArgsFunction: func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
|
return []string{"extra4"}, ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
}
|
||||||
|
childCmd5 := &Command{
|
||||||
|
Use: "child5",
|
||||||
|
Version: "1.1.1",
|
||||||
|
Run: emptyRun,
|
||||||
|
ValidArgsFunction: func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
|
return []string{"extra5"}, ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
}
|
||||||
|
|
||||||
rootCmd.AddCommand(childCmd, childCmd2, childCmd3)
|
rootCmd.AddCommand(childCmd, childCmd2, childCmd3, childCmd4, childCmd5)
|
||||||
|
|
||||||
_ = childCmd.Flags().Bool("bool", false, "A bool flag")
|
_ = childCmd.Flags().Bool("bool", false, "A bool flag")
|
||||||
_ = childCmd.MarkFlagRequired("bool")
|
_ = childCmd.MarkFlagRequired("bool")
|
||||||
@ -3066,6 +3082,10 @@ func TestCompletionCobraFlags(t *testing.T) {
|
|||||||
// Have a command that only adds its own -v flag
|
// Have a command that only adds its own -v flag
|
||||||
_ = childCmd3.Flags().BoolP("verbose", "v", false, "Not a version flag")
|
_ = childCmd3.Flags().BoolP("verbose", "v", false, "Not a version flag")
|
||||||
|
|
||||||
|
// Have a command that DisablesFlagParsing but that also adds its own help and version flags
|
||||||
|
_ = childCmd5.Flags().BoolP("help", "h", false, "My own help")
|
||||||
|
_ = childCmd5.Flags().BoolP("version", "v", false, "My own version")
|
||||||
|
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3196,6 +3216,26 @@ func TestCompletionCobraFlags(t *testing.T) {
|
|||||||
":4",
|
":4",
|
||||||
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"),
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "no completion for --help/-h and --version/-v flags when DisableFlagParsing=true",
|
||||||
|
args: []string{"child4", "-"},
|
||||||
|
expectedOutput: strings.Join([]string{
|
||||||
|
"extra4",
|
||||||
|
":4",
|
||||||
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "completions for program-defined --help/-h and --version/-v flags even when DisableFlagParsing=true",
|
||||||
|
args: []string{"child5", "-"},
|
||||||
|
expectedOutput: strings.Join([]string{
|
||||||
|
"--help",
|
||||||
|
"-h",
|
||||||
|
"--version",
|
||||||
|
"-v",
|
||||||
|
"extra5",
|
||||||
|
":4",
|
||||||
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
|
Loading…
Reference in New Issue
Block a user