Repository: spf13/cobra
File: completions.go (Go)

Code before:
			fmt.Fprintf(out, ":%d\n", directive)

			// Print some helpful info to stderr for the user to understand.
			// Output from stderr must be ignored by the completion script.
			fmt.Fprintf(finalCmd.ErrOrStderr(), "Completion ended with directive: %s\n", directive.string())
		},
	}
	c.AddCommand(completeCmd)
	subCmd, _, err := c.Find(args)
	if err != nil || subCmd.Name() != ShellCompRequestCmd {
		// Only create this special command if it is actually being called.
		// This reduces possible side-effects of creating such a command;
		// for example, having this command would cause problems to a
		// cobra program that only consists of the root command, since this
		// command would cause the root command to suddenly have a subcommand.
		c.RemoveCommand(completeCmd)
	}
}

func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
	// The last argument, which is not completely typed by the user,
	// should not be part of the list of arguments
	toComplete := args[len(args)-1]
	trimmedArgs := args[:len(args)-1]

	var finalCmd *Command
	var finalArgs []string
	var err error
	// Find the real command for which completion must be performed
	// check if we need to traverse here to parse local flags on parent commands
	if c.Root().TraverseChildren {
		finalCmd, finalArgs, err = c.Root().Traverse(trimmedArgs)
	} else {
		// For Root commands that don't specify any value for their Args fields, when we call
		// Find(), if those Root commands don't have any sub-commands, they will accept arguments.
		// However, because we have added the __complete sub-command in the current code path, the
		// call to Find() -> legacyArgs() will return an error if there are any arguments.
		// To avoid this, we first remove the __complete command to get back to having no sub-commands.
		rootCmd := c.Root()
		if len(rootCmd.Commands()) == 1 {
			rootCmd.RemoveCommand(c)
		}

		finalCmd, finalArgs, err = rootCmd.Find(trimmedArgs)
	}
	if err != nil {
		// Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
		return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs)
	}
	finalCmd.ctx = c.ctx


Review comment (suggestion):
Can you do something like this either here or in the tests?

(This is untested pseudocode written on a phone, please check and adapt)

```suggestion
// SliceValue is a reduced version of [pflag.SliceValue]. It is used to detect
// flags that accept multiple values and therefore can provide completion
// multiple times.
type SliceValue interface {
	// GetSlice returns the flag value list as an array of strings.
	GetSlice() []string
}

var _ SliceValue = (*pflag.SliceValue)(nil)
```

The idea is to validate pflag.SliceValue implements the interface you define

Code after:
			fmt.Fprintf(out, ":%d\n", directive)

			// Print some helpful info to stderr for the user to understand.
			// Output from stderr must be ignored by the completion script.
			fmt.Fprintf(finalCmd.ErrOrStderr(), "Completion ended with directive: %s\n", directive.string())
		},
	}
	c.AddCommand(completeCmd)
	subCmd, _, err := c.Find(args)
	if err != nil || subCmd.Name() != ShellCompRequestCmd {
		// Only create this special command if it is actually being called.
		// This reduces possible side-effects of creating such a command;
		// for example, having this command would cause problems to a
		// cobra program that only consists of the root command, since this
		// command would cause the root command to suddenly have a subcommand.
		c.RemoveCommand(completeCmd)
	}
}

// SliceValue is a reduced version of [pflag.SliceValue]. It is used to detect
// flags that accept multiple values and therefore can provide completion
// multiple times.
type SliceValue interface {
	// GetSlice returns the flag value list as an array of strings.
	GetSlice() []string
}

func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
	// The last argument, which is not completely typed by the user,
	// should not be part of the list of arguments
	toComplete := args[len(args)-1]
	trimmedArgs := args[:len(args)-1]

	var finalCmd *Command
	var finalArgs []string
	var err error
	// Find the real command for which completion must be performed
	// check if we need to traverse here to parse local flags on parent commands
	if c.Root().TraverseChildren {
		finalCmd, finalArgs, err = c.Root().Traverse(trimmedArgs)
	} else {
		// For Root commands that don't specify any value for their Args fields, when we call
		// Find(), if those Root commands don't have any sub-commands, they will accept arguments.
		// However, because we have added the __complete sub-command in the current code path, the
		// call to Find() -> legacyArgs() will return an error if there are any arguments.
		// To avoid this, we first remove the __complete command to get back to having no sub-commands.
		rootCmd := c.Root()
		if len(rootCmd.Commands()) == 1 {
			rootCmd.RemoveCommand(c)
		}