diff --git a/bash_completions.go b/bash_completions.go index 8a5315184..db3509120 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 @@ -644,6 +645,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 2fbe6c131..0b60a7c2a 100644 --- a/command.go +++ b/command.go @@ -26,6 +26,7 @@ import ( "path/filepath" "sort" "strings" + "sync" flag "github.com/spf13/pflag" ) @@ -163,6 +164,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 b60f6b200..ba00ad6c2 100644 --- a/completions.go +++ b/completions.go @@ -32,12 +32,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 @@ -135,28 +129,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() + + c.flagCompletionMutex.Lock() + defer c.flagCompletionMutex.Unlock() - if _, exists := flagCompletionFunctions[flag]; exists { + // 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 @@ -502,9 +545,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 } @@ -828,7 +869,6 @@ to your powershell profile. return cmd.Root().GenPowerShellCompletion(out) } return cmd.Root().GenPowerShellCompletionWithDesc(out) - }, } if haveNoDescFlag { @@ -868,7 +908,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 d5aee2501..451a831de 100644 --- a/completions_test.go +++ b/completions_test.go @@ -97,7 +97,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) @@ -112,7 +113,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) @@ -127,7 +129,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) @@ -146,7 +149,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) @@ -186,7 +190,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) @@ -202,7 +207,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) @@ -224,7 +230,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) @@ -246,7 +253,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) @@ -261,7 +269,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) @@ -277,7 +286,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) @@ -294,7 +304,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) @@ -311,7 +322,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) @@ -336,7 +348,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) @@ -351,7 +364,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) @@ -365,7 +379,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) @@ -399,7 +414,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) @@ -415,7 +431,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) @@ -450,7 +467,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) @@ -466,7 +484,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) @@ -482,7 +501,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) @@ -516,7 +536,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) @@ -536,7 +557,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) @@ -551,7 +573,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) @@ -572,7 +595,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) @@ -607,7 +631,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) @@ -627,7 +652,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) @@ -642,7 +668,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) @@ -663,7 +690,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) @@ -708,7 +736,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) @@ -729,7 +758,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--help", "--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) @@ -753,7 +783,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) @@ -782,7 +813,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) @@ -800,7 +832,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) @@ -852,7 +885,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) @@ -870,7 +904,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) @@ -885,7 +920,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) @@ -904,7 +940,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) @@ -921,7 +958,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) @@ -935,7 +973,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) @@ -954,7 +993,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) @@ -976,7 +1016,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) @@ -994,7 +1035,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) @@ -1032,7 +1074,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) @@ -1046,7 +1089,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) @@ -1060,7 +1104,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) @@ -1074,7 +1119,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) @@ -1088,7 +1134,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) @@ -1102,7 +1149,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) @@ -1116,7 +1164,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) @@ -1150,7 +1199,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) @@ -1163,7 +1213,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) @@ -1177,7 +1228,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) @@ -1191,7 +1243,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) @@ -1205,7 +1258,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) @@ -1219,7 +1273,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) @@ -1232,7 +1287,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) @@ -1274,7 +1330,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) @@ -1298,7 +1355,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) @@ -1313,7 +1371,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) @@ -1340,7 +1399,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) @@ -1371,7 +1431,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) @@ -1386,7 +1447,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) @@ -1400,7 +1462,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) @@ -1416,7 +1479,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) @@ -1430,7 +1494,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) @@ -1444,7 +1509,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) @@ -1471,7 +1537,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) @@ -1486,7 +1553,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) @@ -1500,7 +1568,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) @@ -1624,7 +1693,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) @@ -1640,7 +1710,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) @@ -1657,7 +1728,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) @@ -1673,7 +1745,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) @@ -1704,7 +1777,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) @@ -1719,7 +1793,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) @@ -1733,7 +1808,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) @@ -1749,7 +1825,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) @@ -1763,7 +1840,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) @@ -1777,7 +1855,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) @@ -1816,7 +1895,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) @@ -1832,7 +1912,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) @@ -1848,7 +1929,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) @@ -1867,7 +1949,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) @@ -1883,7 +1966,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) @@ -1899,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) @@ -1915,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) @@ -1931,7 +2017,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) @@ -1947,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) @@ -1963,7 +2051,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) @@ -1981,7 +2070,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) @@ -2000,7 +2090,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) @@ -2035,7 +2126,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) @@ -2068,7 +2160,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) @@ -2142,7 +2235,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) @@ -2187,7 +2281,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) @@ -2203,7 +2298,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) @@ -2220,7 +2316,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) @@ -2236,7 +2333,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) @@ -2264,7 +2362,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) @@ -2279,7 +2378,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) @@ -2306,7 +2406,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) @@ -2322,7 +2423,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) @@ -2337,7 +2439,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) @@ -2374,7 +2477,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) @@ -2392,7 +2496,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) @@ -2407,7 +2512,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) @@ -2579,7 +2685,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) @@ -2602,7 +2709,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) @@ -2634,7 +2742,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) @@ -2650,7 +2759,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) @@ -2665,7 +2775,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) @@ -2680,7 +2791,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) @@ -2696,7 +2808,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) @@ -2704,7 +2817,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 } @@ -2737,7 +2849,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) @@ -2759,7 +2872,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) @@ -2788,7 +2902,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) @@ -2804,7 +2919,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) @@ -2831,7 +2947,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) @@ -2877,7 +2994,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", @@ -2890,7 +3008,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", @@ -2900,7 +3019,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", @@ -2908,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: "group ignored if some flags not applicable", @@ -2918,7 +3039,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -2980,7 +3102,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", @@ -2990,7 +3113,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", @@ -2998,7 +3122,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", @@ -3006,7 +3131,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", @@ -3016,7 +3142,8 @@ func TestCompletionForOneRequiredGroupFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3075,7 +3202,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", @@ -3088,7 +3216,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", @@ -3099,7 +3228,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", @@ -3110,7 +3240,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup1", "--ingroup2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3214,70 +3345,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", @@ -3285,7 +3426,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", @@ -3293,7 +3435,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", @@ -3301,7 +3444,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", @@ -3309,14 +3453,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", @@ -3324,7 +3470,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", @@ -3332,7 +3479,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", @@ -3344,7 +3492,8 @@ func TestCompletionCobraFlags(t *testing.T) { "-v", "extra5", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3432,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) @@ -3500,7 +3658,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") }