From 4ee33b3c5bb5a25d8d2236ad3ea99fbeab999838 Mon Sep 17 00:00:00 2001 From: silenceshell Date: Thu, 24 Jun 2021 11:40:44 +0800 Subject: [PATCH] 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 b47f898a..925e6e78 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 5c85c899..ca1743ad 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 04dc71e4..267b6fba 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 }