feat(comp): Add description to fish completions

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
pull/7690/head
Marc Khouzam 6 years ago
parent 0de8672adc
commit 5158348d67

@ -45,6 +45,7 @@ var (
"zsh": runCompletionZsh, "zsh": runCompletionZsh,
"fish": runCompletionFish, "fish": runCompletionFish,
} }
completionNoDesc bool
) )
func newCompletionCmd(out io.Writer) *cobra.Command { func newCompletionCmd(out io.Writer) *cobra.Command {
@ -62,6 +63,7 @@ func newCompletionCmd(out io.Writer) *cobra.Command {
}, },
ValidArgs: shells, ValidArgs: shells,
} }
cmd.PersistentFlags().BoolVar(&completionNoDesc, "no-descriptions", false, "disable completion description for shells that support it")
return cmd return cmd
} }
@ -249,6 +251,10 @@ __helm_bash_source <(__helm_convert_bash_to_zsh)
} }
func runCompletionFish(out io.Writer, cmd *cobra.Command) error { func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
compCmd := completion.CompWithDescRequestCmd
if completionNoDesc {
compCmd = completion.CompRequestCmd
}
fishScript := fmt.Sprintf(`# fish completion for helm -*- shell-script -*- fishScript := fmt.Sprintf(`# fish completion for helm -*- shell-script -*-
function __helm_debug function __helm_debug
@ -272,7 +278,7 @@ function __helm_handle_completion
end end
__helm_debug "emptyArg: $emptyArg" __helm_debug "emptyArg: $emptyArg"
set requestComp "$args[1] __complete $args[2..-1] $emptyArg" set requestComp "$args[1] %[1]s $args[2..-1] $emptyArg"
__helm_debug "Calling $requestComp" __helm_debug "Calling $requestComp"
eval $requestComp 2> /dev/null eval $requestComp 2> /dev/null
end end
@ -289,13 +295,13 @@ function __helm_get_completions
__helm_debug "Completions are: $comps" __helm_debug "Completions are: $comps"
__helm_debug "Directive is: $directive" __helm_debug "Directive is: $directive"
set -l compErr (math (math $directive / %[1]d) %% 2) set -l compErr (math (math $directive / %[2]d) %% 2)
if test $compErr -eq 1 if test $compErr -eq 1
return 0 return 0
end end
set -l nospace (math (math $directive / %[2]d) %% 2) set -l nospace (math (math $directive / %[3]d) %% 2)
set -l nofiles (math (math $directive / %[3]d) %% 2) set -l nofiles (math (math $directive / %[4]d) %% 2)
__helm_debug "nospace: $nospace, nofiles: $nofiles" __helm_debug "nospace: $nospace, nofiles: $nofiles"
@ -325,7 +331,7 @@ complete -c helm -n 'not __helm_get_completions'
# This completion will be run first as complete commands are added FILO. It first clears the cache. # This completion will be run first as complete commands are added FILO. It first clears the cache.
complete -c helm -n 'set -e __helm_cache_completions; __helm_get_completions' -f -a '(__helm_get_completions)' complete -c helm -n 'set -e __helm_cache_completions; __helm_get_completions' -f -a '(__helm_get_completions)'
`, completion.BashCompDirectiveError, completion.BashCompDirectiveNoSpace, completion.BashCompDirectiveNoFileComp) `, compCmd, completion.BashCompDirectiveError, completion.BashCompDirectiveNoSpace, completion.BashCompDirectiveNoFileComp)
out.Write([]byte(fishScript)) out.Write([]byte(fishScript))
return nil return nil

@ -35,9 +35,14 @@ import (
// This should ultimately be pushed down into Cobra. // This should ultimately be pushed down into Cobra.
// ================================================================================== // ==================================================================================
// CompRequestCmd is the name of the hidden command that is used to request const (
// completion results from helm. It is used by the shell completion script. // CompRequestCmd is the name of the hidden command that is used to request
const CompRequestCmd = "__complete" // completion results from helm. It is used by the shell completion script.
CompRequestCmd = "__complete"
// CompWithDescRequestCmd is the name of the hidden command that is used to request
// completion results with their description. It is used by the shell completion script.
CompWithDescRequestCmd = "__completeD"
)
// Global map allowing to find completion functions for commands or flags. // Global map allowing to find completion functions for commands or flags.
var validArgsFunctions = map[interface{}]func(cmd *cobra.Command, args []string, toComplete string) ([]string, BashCompDirective){} var validArgsFunctions = map[interface{}]func(cmd *cobra.Command, args []string, toComplete string) ([]string, BashCompDirective){}
@ -181,12 +186,13 @@ func NewCompleteCmd(settings *cli.EnvSettings, out io.Writer) *cobra.Command {
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
Hidden: true, Hidden: true,
DisableFlagParsing: true, DisableFlagParsing: true,
Aliases: []string{CompWithDescRequestCmd},
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
Short: "Request shell completion choices for the specified command-line", Short: "Request shell completion choices for the specified command-line",
Long: fmt.Sprintf("%[2]s is a special command that is used by the shell completion logic\n%[1]s", Long: fmt.Sprintf("%[2]s is a special command that is used by the shell completion logic\n%[1]s",
"to request completion choices for the specified command-line.", CompRequestCmd), "to request completion choices for the specified command-line.", CompRequestCmd),
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
completions, directive, err := getCompletions(cmd.Root(), args) completions, directive, err := getCompletions(cmd, args)
if err != nil { if err != nil {
CompErrorln(err.Error()) CompErrorln(err.Error())
// Keep going for multiple reasons: // Keep going for multiple reasons:
@ -215,7 +221,7 @@ func NewCompleteCmd(settings *cli.EnvSettings, out io.Writer) *cobra.Command {
} }
} }
func getCompletions(rootCmd *cobra.Command, args []string) ([]string, BashCompDirective, error) { func getCompletions(cmd *cobra.Command, args []string) ([]string, BashCompDirective, error) {
var completions []string var completions []string
// The last argument, which is not completely typed by the user, // The last argument, which is not completely typed by the user,
@ -224,19 +230,20 @@ func getCompletions(rootCmd *cobra.Command, args []string) ([]string, BashCompDi
trimmedArgs := args[:len(args)-1] trimmedArgs := args[:len(args)-1]
// Find the real command for which completion must be performed // Find the real command for which completion must be performed
finalCmd, finalArgs, err := rootCmd.Find(trimmedArgs) finalCmd, finalArgs, err := cmd.Root().Find(trimmedArgs)
if err != nil { if err != nil {
// Unable to find the real command. E.g., helm invalidCmd <TAB> // Unable to find the real command. E.g., helm invalidCmd <TAB>
return completions, BashCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs) return completions, BashCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
} }
includeDesc := (cmd.CalledAs() == CompWithDescRequestCmd)
if isFlag(toComplete) && !strings.Contains(toComplete, "=") { if isFlag(toComplete) && !strings.Contains(toComplete, "=") {
// We are completing a flag name // We are completing a flag name
finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
completions = append(completions, getFlagNameCompletions(flag, toComplete)...) completions = append(completions, getFlagNameCompletions(flag, toComplete, includeDesc)...)
}) })
finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
completions = append(completions, getFlagNameCompletions(flag, toComplete)...) completions = append(completions, getFlagNameCompletions(flag, toComplete, includeDesc)...)
}) })
directive := BashCompDirectiveDefault directive := BashCompDirectiveDefault
@ -263,7 +270,11 @@ func getCompletions(rootCmd *cobra.Command, args []string) ([]string, BashCompDi
// Complete subcommand names // Complete subcommand names
for _, subCmd := range finalCmd.Commands() { for _, subCmd := range finalCmd.Commands() {
if subCmd.IsAvailableCommand() && strings.HasPrefix(subCmd.Name(), toComplete) { if subCmd.IsAvailableCommand() && strings.HasPrefix(subCmd.Name(), toComplete) {
completions = append(completions, subCmd.Name()) comp := subCmd.Name()
if includeDesc {
comp = fmt.Sprintf("%s\t%s", comp, subCmd.Short)
}
completions = append(completions, comp)
} }
} }
@ -313,7 +324,7 @@ func getCompletions(rootCmd *cobra.Command, args []string) ([]string, BashCompDi
return completions, directive, nil return completions, directive, nil
} }
func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string { func getFlagNameCompletions(flag *pflag.Flag, toComplete string, includeDesc bool) []string {
if nonCompletableFlag(flag) { if nonCompletableFlag(flag) {
return []string{} return []string{}
} }
@ -335,6 +346,13 @@ func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
if len(flag.Shorthand) > 0 && strings.HasPrefix(comp, toComplete) { if len(flag.Shorthand) > 0 && strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp) completions = append(completions, comp)
} }
// Add documentation if requested
if includeDesc {
for idx, comp := range completions {
completions[idx] = fmt.Sprintf("%s\t%s", comp, flag.Usage)
}
}
return completions return completions
} }

Loading…
Cancel
Save