feat(cmd): Subcommands for the completion command

Making each shell a subcommand of the 'completion' has multiple
advantages:
- simplifies the code,
- allows to have different flags for each shell,
  for example, a future `--no-descriptions` flag for fish only,
- allows to tailor the help text per shell.

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
pull/8314/head
Marc Khouzam 5 years ago
parent a28d695c43
commit f7c882d55e

@ -21,61 +21,70 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/require"
) )
const completionDesc = ` const completionDesc = `
Generate autocompletions script for Helm for the specified shell (bash or zsh). Generate autocompletions script for Helm for the specified shell.
`
const bashCompDesc = `
Generate the autocompletion script for Helm for the bash shell.
This command can generate shell autocompletions. e.g. To load completions in your current shell session:
$ source <(helm completion bash)
$ helm completion bash To load completions for every new session, execute once:
Linux:
$ helm completion bash > /etc/bash_completion.d/helm
MacOS:
$ helm completion bash > /usr/local/etc/bash_completion.d/helm
`
Can be sourced as such const zshCompDesc = `
Generate the autocompletion script for Helm for the zsh shell.
$ source <(helm completion bash) To load completions in your current shell session:
` $ source <(helm completion zsh)
var ( To load completions for every new session, execute once:
completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{ $ helm completion zsh > "${fpath[1]}/_helm"
"bash": runCompletionBash, `
"zsh": runCompletionZsh,
}
)
func newCompletionCmd(out io.Writer) *cobra.Command { func newCompletionCmd(out io.Writer) *cobra.Command {
shells := []string{}
for s := range completionShells {
shells = append(shells, s)
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "completion SHELL", Use: "completion",
Short: "generate autocompletions script for the specified shell (bash or zsh)", Short: "generate autocompletions script for the specified shell",
Long: completionDesc, Long: completionDesc,
Args: require.NoArgs,
}
bash := &cobra.Command{
Use: "bash",
Short: "generate autocompletions script for bash",
Long: bashCompDesc,
Args: require.NoArgs,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runCompletion(out, cmd, args) return runCompletionBash(out, cmd)
}, },
ValidArgs: shells,
} }
return cmd zsh := &cobra.Command{
} Use: "zsh",
Short: "generate autocompletions script for zsh",
func runCompletion(out io.Writer, cmd *cobra.Command, args []string) error { Long: zshCompDesc,
if len(args) == 0 { Args: require.NoArgs,
return errors.New("shell not specified") DisableFlagsInUseLine: true,
} RunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 1 { return runCompletionZsh(out, cmd)
return errors.New("too many arguments, expected only the shell type") },
}
run, found := completionShells[args[0]]
if !found {
return errors.Errorf("unsupported shell type %q", args[0])
} }
return run(out, cmd) cmd.AddCommand(bash, zsh)
return cmd
} }
func runCompletionBash(out io.Writer, cmd *cobra.Command) error { func runCompletionBash(out io.Writer, cmd *cobra.Command) error {

@ -105,7 +105,8 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
// We only do this when necessary (for the "completion" and "__complete" commands) to avoid the // We only do this when necessary (for the "completion" and "__complete" commands) to avoid the
// risk of a rogue plugin affecting Helm's normal behavior. // risk of a rogue plugin affecting Helm's normal behavior.
subCmd, _, err := baseCmd.Find(os.Args[1:]) subCmd, _, err := baseCmd.Find(os.Args[1:])
if (err == nil && (subCmd.Name() == "completion" || subCmd.Name() == cobra.ShellCompRequestCmd)) || if (err == nil &&
((subCmd.HasParent() && subCmd.Parent().Name() == "completion") || subCmd.Name() == cobra.ShellCompRequestCmd)) ||
/* for the tests */ subCmd == baseCmd.Root() { /* for the tests */ subCmd == baseCmd.Root() {
loadCompletionForPlugin(c, plug) loadCompletionForPlugin(c, plug)
} }

Loading…
Cancel
Save