Skip to content

Commit

Permalink
Fix a logic lookup bug that was kind enough to surface at the good
Browse files Browse the repository at this point in the history
moment.
  • Loading branch information
maxlandon committed Nov 2, 2023
1 parent f5848b6 commit 5aadb0d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
22 changes: 18 additions & 4 deletions completions.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,27 @@ func (c *Command) GetFlagCompletionFunc(flag *pflag.Flag) (func(cmd *Command, ar
}

// GetFlagCompletionByName returns the completion function for the given flag in the command by name, if available.
// If the flag is not found in the command's local flags, it looks into the persistent flags, which might belong to one of the command's parents.
func (c *Command) GetFlagCompletionFuncByName(flagName string) (func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective), bool) {
flag := c.Flags().Lookup(flagName)
if flag == nil {
return nil, false
// Attempt to find it in the local flags.
if flag := c.Flags().Lookup(flagName); flag != nil {
return c.GetFlagCompletionFunc(flag)
}

// Or try to find it in the "command-specific" persistent flags.
if flag := c.PersistentFlags().Lookup(flagName); flag != nil {
return c.GetFlagCompletionFunc(flag)
}

// Else, check all persistent flags belonging to one of the parents.
// This ensures that we won't return the completion function of a
// parent's LOCAL flag.
if flag := c.InheritedFlags().Lookup(flagName); flag != nil {
return c.GetFlagCompletionFunc(flag)
}

return c.GetFlagCompletionFunc(flag)
// No flag exists either locally, or as one of the parent persistent flags.
return nil, false
}

// initializeCompletionStorage is (and should be) called in all
Expand Down
15 changes: 12 additions & 3 deletions completions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3581,21 +3581,30 @@ func TestGetFlagCompletion(t *testing.T) {
rootCmd := &Command{Use: "root", Run: emptyRun}

rootCmd.Flags().String("rootflag", "", "root flag")
_ = rootCmd.RegisterFlagCompletionFunc("rootflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
err := rootCmd.RegisterFlagCompletionFunc("rootflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
return []string{"rootvalue"}, ShellCompDirectiveKeepOrder
})
if err != nil {
t.Error(err)
}

rootCmd.PersistentFlags().String("persistentflag", "", "persistent flag")
_ = rootCmd.RegisterFlagCompletionFunc("persistentflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
err = rootCmd.RegisterFlagCompletionFunc("persistentflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
return []string{"persistentvalue"}, ShellCompDirectiveDefault
})
if err != nil {
t.Error(err)
}

childCmd := &Command{Use: "child", Run: emptyRun}

childCmd.Flags().String("childflag", "", "child flag")
_ = childCmd.RegisterFlagCompletionFunc("childflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
err = childCmd.RegisterFlagCompletionFunc("childflag", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
return []string{"childvalue"}, ShellCompDirectiveNoFileComp | ShellCompDirectiveNoSpace
})
if err != nil {
t.Error(err)
}

rootCmd.AddCommand(childCmd)

Expand Down

0 comments on commit 5aadb0d

Please sign in to comment.