mirror of
https://github.com/spf13/cobra
synced 2025-04-01 20:39:12 +00:00
feat: add CompletionWithDesc helper
The code has also been refactored to use a type alias for completion and a completion helper Using a type alias is a non-breaking change and it makes the code more readable and easier to understand. Signed-off-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com>
This commit is contained in:
parent
17b6dca2ff
commit
f80a6ab97a
2 changed files with 35 additions and 19 deletions
|
@ -82,7 +82,7 @@ type Command struct {
|
|||
Example string
|
||||
|
||||
// ValidArgs is list of all valid non-flag arguments that are accepted in shell completions
|
||||
ValidArgs []string
|
||||
ValidArgs []CompletionChoice
|
||||
// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion.
|
||||
// It is a dynamic version of using ValidArgs.
|
||||
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
|
||||
|
@ -94,7 +94,7 @@ type Command struct {
|
|||
// ArgAliases is List of aliases for ValidArgs.
|
||||
// These are not suggested to the user in the shell completion,
|
||||
// but accepted if entered manually.
|
||||
ArgAliases []string
|
||||
ArgAliases []CompletionChoice
|
||||
|
||||
// BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator.
|
||||
// For portability with other shells, it is recommended to instead use ValidArgsFunction
|
||||
|
|
|
@ -117,15 +117,31 @@ type CompletionOptions struct {
|
|||
HiddenDefaultCmd bool
|
||||
}
|
||||
|
||||
// CompletionChoice is a string that can be used for completions
|
||||
//
|
||||
// two formats are supported:
|
||||
// - the name of the flag
|
||||
// - the name of the flag with its description (separated by a tab)
|
||||
//
|
||||
// [CompletionChoiceWithDescription] can be used to create a completion string with a description using the TAB separator.
|
||||
//
|
||||
// Note: Go type alias is used to provide a more descriptive name in the documentation, but any string can be used.
|
||||
type CompletionChoice = string
|
||||
|
||||
// CompletionFunc is a function that provides completion results.
|
||||
type CompletionFunc func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||
type CompletionFunc func(cmd *Command, args []CompletionChoice, toComplete string) ([]string, ShellCompDirective)
|
||||
|
||||
// CompletionChoiceWithDescription returns a CompletionChoice with a description
|
||||
func CompletionChoiceWithDescription(name, desc string) CompletionChoice {
|
||||
return name + "\t" + desc
|
||||
}
|
||||
|
||||
// NoFileCompletions can be used to disable file completion for commands that should
|
||||
// not trigger file completions.
|
||||
//
|
||||
// This method satisfies [CompletionFunc].
|
||||
// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction].
|
||||
func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||
func NoFileCompletions(cmd *Command, args []CompletionChoice, toComplete string) ([]string, ShellCompDirective) {
|
||||
return nil, ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
|
@ -134,8 +150,8 @@ func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string
|
|||
//
|
||||
// This method returns a function that satisfies [CompletionFunc]
|
||||
// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction].
|
||||
func FixedCompletions(choices []string, directive ShellCompDirective) CompletionFunc {
|
||||
return func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||
func FixedCompletions(choices []CompletionChoice, directive ShellCompDirective) CompletionFunc {
|
||||
return func(cmd *Command, args []CompletionChoice, toComplete string) ([]string, ShellCompDirective) {
|
||||
return choices, directive
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +306,7 @@ type SliceValue interface {
|
|||
GetSlice() []string
|
||||
}
|
||||
|
||||
func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
|
||||
func (c *Command) getCompletions(args []string) (*Command, []CompletionChoice, 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]
|
||||
|
@ -318,7 +334,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
}
|
||||
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)
|
||||
return c, []CompletionChoice{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs)
|
||||
}
|
||||
finalCmd.ctx = c.ctx
|
||||
|
||||
|
@ -348,7 +364,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
|
||||
// Parse the flags early so we can check if required flags are set
|
||||
if err = finalCmd.ParseFlags(finalArgs); err != nil {
|
||||
return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
|
||||
return finalCmd, []CompletionChoice{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
|
||||
}
|
||||
|
||||
realArgCount := finalCmd.Flags().NArg()
|
||||
|
@ -360,14 +376,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
if flagErr != nil {
|
||||
// If error type is flagCompError and we don't want flagCompletion we should ignore the error
|
||||
if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) {
|
||||
return finalCmd, []string{}, ShellCompDirectiveDefault, flagErr
|
||||
return finalCmd, []CompletionChoice{}, ShellCompDirectiveDefault, flagErr
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the --help or --version flags. If they are present,
|
||||
// there should be no further completions.
|
||||
if helpOrVersionFlagPresent(finalCmd) {
|
||||
return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil
|
||||
return finalCmd, []CompletionChoice{}, ShellCompDirectiveNoFileComp, nil
|
||||
}
|
||||
|
||||
// We only remove the flags from the arguments if DisableFlagParsing is not set.
|
||||
|
@ -396,11 +412,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
return finalCmd, subDir, ShellCompDirectiveFilterDirs, nil
|
||||
}
|
||||
// Directory completion
|
||||
return finalCmd, []string{}, ShellCompDirectiveFilterDirs, nil
|
||||
return finalCmd, []CompletionChoice{}, ShellCompDirectiveFilterDirs, nil
|
||||
}
|
||||
}
|
||||
|
||||
var completions []string
|
||||
var completions []CompletionChoice
|
||||
var directive ShellCompDirective
|
||||
|
||||
// Enforce flag groups before doing flag completions
|
||||
|
@ -542,7 +558,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
if completionFn != nil {
|
||||
// Go custom completion defined for this flag or command.
|
||||
// Call the registered completion function to get the completions.
|
||||
var comps []string
|
||||
var comps []CompletionChoice
|
||||
comps, directive = completionFn(finalCmd, finalArgs, toComplete)
|
||||
completions = append(completions, comps...)
|
||||
}
|
||||
|
@ -562,12 +578,12 @@ func helpOrVersionFlagPresent(cmd *Command) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
|
||||
func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []CompletionChoice {
|
||||
if nonCompletableFlag(flag) {
|
||||
return []string{}
|
||||
return []CompletionChoice{}
|
||||
}
|
||||
|
||||
var completions []string
|
||||
var completions []CompletionChoice
|
||||
flagName := "--" + flag.Name
|
||||
if strings.HasPrefix(flagName, toComplete) {
|
||||
// Flag without the =
|
||||
|
@ -595,8 +611,8 @@ func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
|
|||
return completions
|
||||
}
|
||||
|
||||
func completeRequireFlags(finalCmd *Command, toComplete string) []string {
|
||||
var completions []string
|
||||
func completeRequireFlags(finalCmd *Command, toComplete string) []CompletionChoice {
|
||||
var completions []CompletionChoice
|
||||
|
||||
doCompleteRequiredFlags := func(flag *pflag.Flag) {
|
||||
if _, present := flag.Annotations[BashCompOneRequiredFlag]; present {
|
||||
|
|
Loading…
Reference in a new issue