diff --git a/bash_completions.go b/bash_completions.go index f4d198cb..8f5bc117 100644 --- a/bash_completions.go +++ b/bash_completions.go @@ -534,9 +534,10 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { // prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags func prepareCustomAnnotationsForFlags(cmd *Command) { - flagCompletionMutex.RLock() - defer flagCompletionMutex.RUnlock() - for flag := range flagCompletionFunctions { + cmd.initializeCompletionStorage() + cmd.flagCompletionMutex.RLock() + defer cmd.flagCompletionMutex.RUnlock() + for flag := range cmd.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 @@ -641,6 +642,7 @@ func writeCmdAliases(buf io.StringWriter, cmd *Command) { WriteStringAndCheck(buf, ` fi`) WriteStringAndCheck(buf, "\n") } + func writeArgAliases(buf io.StringWriter, cmd *Command) { WriteStringAndCheck(buf, " noun_aliases=()\n") sort.Strings(cmd.ArgAliases) diff --git a/command.go b/command.go index 19602946..840a281b 100644 --- a/command.go +++ b/command.go @@ -25,6 +25,7 @@ import ( "os" "sort" "strings" + "sync" flag "github.com/spf13/pflag" ) @@ -164,6 +165,13 @@ type Command struct { // that we can use on every pflag set and children commands globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + // flagsCompletions contrains completions for arbitrary lists of flags. + // Those flags may or may not actually strictly belong to the command in the function, + // but registering completions for them through the command allows for garbage-collecting. + flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + // lock for reading and writing from flagCompletionFunctions + flagCompletionMutex *sync.RWMutex + // usageFunc is usage func defined by user. usageFunc func(*Command) error // usageTemplate is usage template defined by user. diff --git a/completions.go b/completions.go index 0862d3f6..a271c6ca 100644 --- a/completions.go +++ b/completions.go @@ -34,12 +34,6 @@ const ( ShellCompNoDescRequestCmd = "__completeNoDesc" ) -// Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it. -var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} - -// lock for reading and writing from flagCompletionFunctions -var flagCompletionMutex = &sync.RWMutex{} - // ShellCompDirective is a bit map representing the different behaviors the shell // can be instructed to have once completions have been provided. type ShellCompDirective int @@ -137,28 +131,77 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman if flag == nil { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName) } - flagCompletionMutex.Lock() - defer flagCompletionMutex.Unlock() + // Ensure none of our relevant fields are nil. + c.initializeCompletionStorage() - if _, exists := flagCompletionFunctions[flag]; exists { + c.flagCompletionMutex.Lock() + defer c.flagCompletionMutex.Unlock() + + // And attempt to bind the completion. + if _, exists := c.flagCompletionFunctions[flag]; exists { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName) } - flagCompletionFunctions[flag] = f + c.flagCompletionFunctions[flag] = f return nil } -// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. -func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) { - flag := c.Flag(flagName) - if flag == nil { +// GetFlagCompletion returns the completion function for the given flag, if available. +func (c *Command) GetFlagCompletionFunc(flag *pflag.Flag) (func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective), bool) { + c.initializeCompletionStorage() + + c.flagCompletionMutex.RLock() + defer c.flagCompletionMutex.RUnlock() + + completionFunc, exists := c.flagCompletionFunctions[flag] + + // If found it here, return now + if completionFunc != nil && exists { + return completionFunc, exists + } + + // If we are already at the root command level, return anyway + if !c.HasParent() { return nil, false } - flagCompletionMutex.RLock() - defer flagCompletionMutex.RUnlock() + // Or walk up the command tree. + return c.Parent().GetFlagCompletionFunc(flag) +} - completionFunc, exists := flagCompletionFunctions[flag] - return completionFunc, exists +// 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) { + // 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) + } + + // No flag exists either locally, or as one of the parent persistent flags. + return nil, false +} + +// initializeCompletionStorage is (and should be) called in all +// functions that make use of the command's flag completion functions. +func (c *Command) initializeCompletionStorage() { + if c.flagCompletionMutex == nil { + c.flagCompletionMutex = new(sync.RWMutex) + } + + if c.flagCompletionFunctions == nil { + c.flagCompletionFunctions = make(map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective), 0) + } } // Returns a string listing the different directive enabled in the specified parameter @@ -521,9 +564,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 && flagCompletion { - flagCompletionMutex.RLock() - completionFn = flagCompletionFunctions[flag] - flagCompletionMutex.RUnlock() + completionFn, _ = finalCmd.GetFlagCompletionFunc(flag) } else { completionFn = finalCmd.ValidArgsFunction } @@ -847,7 +888,6 @@ to your powershell profile. return cmd.Root().GenPowerShellCompletion(out) } return cmd.Root().GenPowerShellCompletionWithDesc(out) - }, } if haveNoDescFlag { @@ -887,7 +927,7 @@ func CompDebug(msg string, printToStdErr bool) { // variable BASH_COMP_DEBUG_FILE to the path of some file to be used. if path := os.Getenv("BASH_COMP_DEBUG_FILE"); path != "" { f, err := os.OpenFile(path, - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) if err == nil { defer f.Close() WriteStringAndCheck(f, msg) diff --git a/completions_test.go b/completions_test.go index a8f378eb..c4a67160 100644 --- a/completions_test.go +++ b/completions_test.go @@ -98,7 +98,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -113,7 +114,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -128,7 +130,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -147,7 +150,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help\tHelp about any command", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -187,7 +191,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -203,7 +208,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -225,7 +231,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -247,7 +254,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -262,7 +270,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -278,7 +287,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -295,7 +305,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -312,7 +323,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -337,7 +349,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -352,7 +365,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "one", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -366,7 +380,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -400,7 +415,8 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -416,7 +432,8 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -451,7 +468,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -467,7 +485,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -483,7 +502,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild\tThe child command", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -517,7 +537,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -537,7 +558,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--second", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -552,7 +574,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--first", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -573,7 +596,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -608,7 +632,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "completion\tGenerate the autocompletion script for the specified shell", "help\tHelp about any command", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -628,7 +653,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--second\tsecond flag", "-s\tsecond flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -643,7 +669,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { expected = strings.Join([]string{ "--first\tfirst flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -664,7 +691,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--version\tversion for childCmd", "-v\tversion for childCmd", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -735,7 +763,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -757,7 +786,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--multi", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -783,7 +813,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -815,7 +846,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--slice", "-l", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -834,7 +866,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { expected = strings.Join([]string{ "-a", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -886,7 +919,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -904,7 +938,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--requiredPersistent", "-p", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -919,7 +954,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--release", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -938,7 +974,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-s", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -955,7 +992,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--subRequired", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -969,7 +1007,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--subNotRequired", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -988,7 +1027,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1010,7 +1050,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-r", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1028,7 +1069,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1066,7 +1108,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1080,7 +1123,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "log", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1094,7 +1138,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1108,7 +1153,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1122,7 +1168,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1136,7 +1183,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1150,7 +1198,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "txt", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1184,7 +1233,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1197,7 +1247,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1211,7 +1262,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1225,7 +1277,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1239,7 +1292,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1253,7 +1307,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1266,7 +1321,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1308,7 +1364,8 @@ func TestValidArgsFuncCmdContext(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1332,7 +1389,8 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1347,7 +1405,8 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1374,7 +1433,8 @@ func TestValidArgsFuncSingleCmdInvalidArg(t *testing.T) { expected := strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1405,7 +1465,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1420,7 +1481,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1434,7 +1496,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1450,7 +1513,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "three", "four", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1464,7 +1528,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "three", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1478,7 +1543,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1505,7 +1571,8 @@ func TestValidArgsFuncAliases(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1520,7 +1587,8 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1534,7 +1602,8 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1658,7 +1727,8 @@ func TestFlagCompletionInGo(t *testing.T) { "2", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1674,7 +1744,8 @@ func TestFlagCompletionInGo(t *testing.T) { "1", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1691,7 +1762,8 @@ func TestFlagCompletionInGo(t *testing.T) { "myfile.json", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1707,7 +1779,8 @@ func TestFlagCompletionInGo(t *testing.T) { "file.yaml", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1738,7 +1811,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "one\tThe first", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1753,7 +1827,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1767,7 +1842,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1783,7 +1859,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "three\tThe third", "four\tThe fourth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1797,7 +1874,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "three\tThe third", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1811,7 +1889,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1850,7 +1929,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--help\thelp for child", "--string\ttest string flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1866,7 +1946,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1882,7 +1963,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1901,7 +1983,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1917,7 +2000,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1933,7 +2017,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1949,7 +2034,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1965,7 +2051,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1981,7 +2068,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1997,7 +2085,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2015,7 +2104,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { expected = strings.Join([]string{ "--validarg", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2034,7 +2124,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "--toComp=ab", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2069,7 +2160,8 @@ func TestFlagCompletionWorksRootCommandAddedAfterFlags(t *testing.T) { expected := strings.Join([]string{ "myval", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2102,7 +2194,8 @@ func TestFlagCompletionForPersistentFlagsCalledFromSubCmd(t *testing.T) { expected := strings.Join([]string{ "myval", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2176,7 +2269,8 @@ func TestFlagCompletionConcurrentRegistration(t *testing.T) { expected := strings.Join([]string{ flagName, ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2221,7 +2315,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "2\tThe second", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2237,7 +2332,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "1\tThe first", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2254,7 +2350,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "myfile.json\tJSON format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2270,7 +2367,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "file.yaml\tYAML format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2298,7 +2396,8 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2313,7 +2412,8 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { expected = strings.Join([]string{ "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2340,7 +2440,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2356,7 +2457,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2371,7 +2473,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "trois", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2408,7 +2511,8 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2426,7 +2530,8 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", // " help help" is a valid command, so should be completed ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2441,7 +2546,8 @@ func TestCompleteHelp(t *testing.T) { expected = strings.Join([]string{ "child3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2613,7 +2719,8 @@ func TestCompleteCompletion(t *testing.T) { "powershell", "zsh", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2636,7 +2743,8 @@ func TestCompleteCompletion(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2668,7 +2776,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2684,7 +2793,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2699,7 +2809,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2714,7 +2825,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2730,7 +2842,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2738,7 +2851,6 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { } func TestCompleteWithDisableFlagParsing(t *testing.T) { - flagValidArgs := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { return []string{"--flag", "-f"}, ShellCompDirectiveNoFileComp } @@ -2771,7 +2883,8 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--flag", "-f", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2793,7 +2906,8 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--nonPersistent", "-n", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2822,7 +2936,8 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2838,7 +2953,8 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2865,7 +2981,8 @@ func TestFixedCompletions(t *testing.T) { "banana", "orange", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2911,7 +3028,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "flags in group suggested with - prefix", @@ -2924,7 +3042,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when flag in group present, other flags in group suggested even without - prefix", @@ -2934,7 +3053,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when all flags in group present, flags not suggested without - prefix", @@ -2942,7 +3062,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -2952,7 +3073,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3014,7 +3136,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { "--ingroup3", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "flags in group suggested with - prefix", @@ -3024,7 +3147,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { "--ingroup2", "--ingroup3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when any flag in group present, other flags in group not suggested without - prefix", @@ -3032,7 +3156,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when all flags in group present, flags not suggested without - prefix", @@ -3040,7 +3165,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -3050,7 +3176,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3109,7 +3236,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "flags in mutually exclusive group suggested with the - prefix", @@ -3122,7 +3250,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when flag in mutually exclusive group present, other flags in group not suggested even with the - prefix", @@ -3133,7 +3262,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "-h", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -3144,7 +3274,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup1", "--ingroup2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3248,70 +3379,80 @@ func TestCompletionCobraFlags(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --help flag", args: []string{"--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -h flag", args: []string{"-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --version flag", args: []string{"--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag", args: []string{"-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --help flag even with other completions", args: []string{"child", "--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -h flag even with other completions", args: []string{"child", "-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --version flag even with other completions", args: []string{"child", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag even with other completions", args: []string{"child", "-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag even with other flag completions", args: []string{"child", "-v", "-"}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --help flag when created by program", @@ -3319,7 +3460,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -h flag when created by program", @@ -3327,7 +3469,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --version flag when created by program", @@ -3335,7 +3478,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -v flag when created by program", @@ -3343,14 +3487,16 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --version when only -v flag was created by program", args: []string{"child3", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -v flag when only -v flag was created by program", @@ -3358,7 +3504,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra3", ":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", @@ -3366,7 +3513,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra4", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completions for program-defined --help/-h and --version/-v flags even when DisableFlagParsing=true", @@ -3378,7 +3526,8 @@ func TestCompletionCobraFlags(t *testing.T) { "-v", "extra5", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3466,21 +3615,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) @@ -3534,7 +3692,7 @@ func TestGetFlagCompletion(t *testing.T) { for _, tc := range testcases { t.Run(tc.desc, func(t *testing.T) { - compFunc, exists := tc.cmd.GetFlagCompletionFunc(tc.flagName) + compFunc, exists := tc.cmd.GetFlagCompletionFuncByName(tc.flagName) if tc.exists != exists { t.Errorf("Unexpected result looking for flag completion function") }