From 4ee33b3c5bb5a25d8d2236ad3ea99fbeab999838 Mon Sep 17 00:00:00 2001 From: silenceshell Date: Thu, 24 Jun 2021 11:40:44 +0800 Subject: [PATCH 1/3] fix-RegisterFlagCompletionFunc-concurrent --- bash_completions.go | 2 +- command.go | 3 +++ completions.go | 13 +++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bash_completions.go b/bash_completions.go index b47f898a2..925e6e787 100644 --- a/bash_completions.go +++ b/bash_completions.go @@ -512,7 +512,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { // Setup annotations for go completions for registered flags func prepareCustomAnnotationsForFlags(cmd *Command) { - for flag := range flagCompletionFunctions { + for flag := range cmd.Root().flagCompletionFunctions { // Make sure the completion script calls the __*_go_custom_completion function for // every registered flag. We need to do this here (and not when the flag was registered // for completion) so that we can know the root command name for the prefix diff --git a/command.go b/command.go index 5c85c899d..ca1743ad0 100644 --- a/command.go +++ b/command.go @@ -88,6 +88,9 @@ type Command struct { // group commands. Annotations map[string]string + //flagCompletionFunctions is map of flag completion functions. + flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + // Version defines the version for this command. If this value is non-empty and the command does not // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, // will print content of the "Version" variable. A shorthand "v" flag will also be added if the diff --git a/completions.go b/completions.go index 04dc71e40..267b6fbab 100644 --- a/completions.go +++ b/completions.go @@ -17,9 +17,6 @@ const ( ShellCompNoDescRequestCmd = "__completeNoDesc" ) -// Global map of flag completion functions. -var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} - // ShellCompDirective is a bit map representing the different behaviors the shell // can be instructed to have once completions have been provided. type ShellCompDirective int @@ -95,10 +92,14 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman if flag == nil { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName) } - if _, exists := flagCompletionFunctions[flag]; exists { + + if _, exists := c.Root().flagCompletionFunctions[flag]; exists { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName) } - flagCompletionFunctions[flag] = f + if c.Root().flagCompletionFunctions == nil { + c.Root().flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} + } + c.Root().flagCompletionFunctions[flag] = f return nil } @@ -375,7 +376,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi // Find the completion function for the flag or command var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) if flag != nil { - completionFn = flagCompletionFunctions[flag] + completionFn = c.Root().flagCompletionFunctions[flag] } else { completionFn = finalCmd.ValidArgsFunction } From 16f2a0735a9362ec5e68303efbc2774fcd46544c Mon Sep 17 00:00:00 2001 From: silenceshell Date: Thu, 24 Jun 2021 13:51:23 +0800 Subject: [PATCH 2/3] set to root command --- completions.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/completions.go b/completions.go index 267b6fbab..cdeed0007 100644 --- a/completions.go +++ b/completions.go @@ -93,13 +93,14 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName) } - if _, exists := c.Root().flagCompletionFunctions[flag]; exists { + root := c.Root() + if _, exists := root.flagCompletionFunctions[flag]; exists { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName) } - if c.Root().flagCompletionFunctions == nil { - c.Root().flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} + if root.flagCompletionFunctions == nil { + root.flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} } - c.Root().flagCompletionFunctions[flag] = f + root.flagCompletionFunctions[flag] = f return nil } From 75cfcdcd47c2042c63b36bebc004ac8b15df1ad9 Mon Sep 17 00:00:00 2001 From: silenceshell Date: Thu, 24 Jun 2021 14:51:27 +0000 Subject: [PATCH 3/3] move to non-public fields --- command.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/command.go b/command.go index ca1743ad0..37cdd8a26 100644 --- a/command.go +++ b/command.go @@ -88,9 +88,6 @@ type Command struct { // group commands. Annotations map[string]string - //flagCompletionFunctions is map of flag completion functions. - flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) - // Version defines the version for this command. If this value is non-empty and the command does not // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, // will print content of the "Version" variable. A shorthand "v" flag will also be added if the @@ -144,6 +141,9 @@ type Command struct { // that we can use on every pflag set and children commands globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + //flagCompletionFunctions is map of flag completion functions. + flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + // usageFunc is usage func defined by user. usageFunc func(*Command) error // usageTemplate is usage template defined by user.