diff options
author | Paul Holzinger <paul.holzinger@web.de> | 2020-09-10 22:36:19 +0200 |
---|---|---|
committer | Paul Holzinger <paul.holzinger@web.de> | 2020-11-12 11:32:03 +0100 |
commit | df4bf5c584f264bdefef5cb30d85c036260eff8f (patch) | |
tree | 8d71634cc63feac5020dfdfc745d178457b50805 /vendor/github.com/spf13/cobra/custom_completions.go | |
parent | ea753128952e1a6d4b56cc80d232f6dbfb420ba5 (diff) | |
download | podman-df4bf5c584f264bdefef5cb30d85c036260eff8f.tar.gz podman-df4bf5c584f264bdefef5cb30d85c036260eff8f.tar.bz2 podman-df4bf5c584f264bdefef5cb30d85c036260eff8f.zip |
Vendor in some cobra PRs to improve the completion experience.
This is only temporary until the cobra following PRs are merged:
- PR#1258 Custom completion handle multiple shorhand flags together
- PR#1249 Fix fish handling of "ShellCompDirectiveNoSpace" and file completion
- PR#1213 Fix zsh completion handling of nospace and file completion
- PR#1146 Bash completion V2 with completion descriptions
Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
Diffstat (limited to 'vendor/github.com/spf13/cobra/custom_completions.go')
-rw-r--r-- | vendor/github.com/spf13/cobra/custom_completions.go | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/vendor/github.com/spf13/cobra/custom_completions.go b/vendor/github.com/spf13/cobra/custom_completions.go index f9e88e081..e2c68ae1e 100644 --- a/vendor/github.com/spf13/cobra/custom_completions.go +++ b/vendor/github.com/spf13/cobra/custom_completions.go @@ -51,6 +51,11 @@ const ( // obtain the same behavior but only for flags. ShellCompDirectiveFilterDirs + // For internal use only. + // Used to maintain backwards-compatibility with the legacy bash custom completions. + shellCompDirectiveLegacyCustomComp + shellCompDirectiveLegacyCustomArgsComp + // =========================================================================== // All directives using iota should be above this one. @@ -94,6 +99,12 @@ func (d ShellCompDirective) string() string { if d&ShellCompDirectiveFilterDirs != 0 { directives = append(directives, "ShellCompDirectiveFilterDirs") } + if d&shellCompDirectiveLegacyCustomComp != 0 { + directives = append(directives, "shellCompDirectiveLegacyCustomComp") + } + if d&shellCompDirectiveLegacyCustomArgsComp != 0 { + directives = append(directives, "shellCompDirectiveLegacyCustomArgsComp") + } if len(directives) == 0 { directives = append(directives, "ShellCompDirectiveDefault") } @@ -149,10 +160,6 @@ func (c *Command) initCompleteCmd(args []string) { fmt.Fprintln(finalCmd.OutOrStdout(), comp) } - if directive >= shellCompDirectiveMaxValue { - directive = ShellCompDirectiveDefault - } - // As the last printout, print the completion directive for the completion script to parse. // The directive integer must be that last character following a single colon (:). // The completion script expects :<directive> @@ -362,6 +369,10 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi var comps []string comps, directive = completionFn(finalCmd, finalArgs, toComplete) completions = append(completions, comps...) + } else { + // If there is no Go custom completion defined, check for legacy bash + // custom completion to preserve backwards-compatibility + completions, directive = checkLegacyCustomCompletion(finalCmd, finalArgs, flag, completions, directive) } return finalCmd, completions, directive, nil @@ -442,7 +453,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p if len(lastArg) > 0 && lastArg[0] == '-' { if index := strings.Index(lastArg, "="); index >= 0 { // Flag with an = - flagName = strings.TrimLeft(lastArg[:index], "-") + if strings.HasPrefix(lastArg[:index], "--") { + // Flag has full name + flagName = lastArg[2:index] + } else { + // Flag is shorthand + // We have to get the last shorthand flag name + // e.g. `-asd` => d to provide the correct completion + // https://github.com/spf13/cobra/issues/1257 + flagName = lastArg[index-1 : index] + } lastArg = lastArg[index+1:] flagWithEqual = true } else { @@ -459,8 +479,16 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p // If the flag contains an = it means it has already been fully processed, // so we don't need to deal with it here. if index := strings.Index(prevArg, "="); index < 0 { - flagName = strings.TrimLeft(prevArg, "-") - + if strings.HasPrefix(prevArg, "--") { + // Flag has full name + flagName = prevArg[2:] + } else { + // Flag is shorthand + // We have to get the last shorthand flag name + // e.g. `-asd` => d to provide the correct completion + // https://github.com/spf13/cobra/issues/1257 + flagName = prevArg[len(prevArg)-1:] + } // Remove the uncompleted flag or else there could be an error created // for an invalid value for that flag trimmedArgs = args[:len(args)-1] @@ -513,6 +541,65 @@ func findFlag(cmd *Command, name string) *pflag.Flag { return cmd.Flag(name) } +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 +} + +// This function checks if legacy bash custom completion should be performed and if so, +// it provides the shell script with the necessary information. +func checkLegacyCustomCompletion(cmd *Command, args []string, flag *pflag.Flag, completions []string, directive ShellCompDirective) ([]string, ShellCompDirective) { + // Check if any legacy custom completion is defined for the program + if len(cmd.Root().BashCompletionFunction) > 0 { + // Legacy custom completion is only triggered if no other completions were found. + if len(completions) == 0 { + if flag != nil { + // For legacy custom flag completion, we must let the script know the bash + // functions it should call based on the content of the annotation BashCompCustom. + if values, present := flag.Annotations[BashCompCustom]; present { + if len(values) > 0 { + handlers := strings.Join(values, "; ") + // We send the commands to set the shell variables that are needed + // for legacy custom completions followed by the functions to call + // to perform the actual flag completion + completions = append(prepareLegacyCustomCompletionVars(cmd, args), handlers) + directive = directive | shellCompDirectiveLegacyCustomComp + } + } + } else { + // Check if the legacy custom_func is defined. + // This check will work for both "__custom_func" and "__<program>_custom_func". + // This could happen if the program defined some functions for legacy flag completion + // but not the legacy custom_func. + if strings.Contains(cmd.Root().BashCompletionFunction, "_custom_func") { + // For legacy args completion, the script already knows what to call + // so we only need to tell it the commands to set the shell variables needed + completions = prepareLegacyCustomCompletionVars(cmd, args) + directive = directive | shellCompDirectiveLegacyCustomComp | shellCompDirectiveLegacyCustomArgsComp + } + } + } + } + return completions, directive +} + +// The original bash completion script had some shell variables that are used by legacy bash +// custom completions. Let's set those variables to allow those legacy custom completions +// to continue working. +func prepareLegacyCustomCompletionVars(cmd *Command, args []string) []string { + var compVarCmds []string + + // "last_command" variable + commandName := cmd.CommandPath() + commandName = strings.Replace(commandName, " ", "_", -1) + commandName = strings.Replace(commandName, ":", "__", -1) + compVarCmds = append(compVarCmds, fmt.Sprintf("last_command=%s", commandName)) + + // "nouns" array variable + compVarCmds = append(compVarCmds, fmt.Sprintf("nouns=(%s)", strings.Join(args, " "))) + + return compVarCmds +} + // CompDebug prints the specified string to the same file as where the // completion script prints its logs. // Note that completion printouts should never be on stdout as they would |