github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/cmd/helm/completion.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package main
    17  
    18  import (
    19  	"fmt"
    20  	"io"
    21  	"os"
    22  	"path/filepath"
    23  
    24  	"github.com/spf13/cobra"
    25  
    26  	"github.com/stefanmcshane/helm/cmd/helm/require"
    27  )
    28  
    29  const completionDesc = `
    30  Generate autocompletion scripts for Helm for the specified shell.
    31  `
    32  const bashCompDesc = `
    33  Generate the autocompletion script for Helm for the bash shell.
    34  
    35  To load completions in your current shell session:
    36  
    37      source <(helm completion bash)
    38  
    39  To load completions for every new session, execute once:
    40  - Linux:
    41  
    42        helm completion bash > /etc/bash_completion.d/helm
    43  
    44  - MacOS:
    45  
    46        helm completion bash > /usr/local/etc/bash_completion.d/helm
    47  `
    48  
    49  const zshCompDesc = `
    50  Generate the autocompletion script for Helm for the zsh shell.
    51  
    52  To load completions in your current shell session:
    53  
    54      source <(helm completion zsh)
    55  
    56  To load completions for every new session, execute once:
    57  
    58      helm completion zsh > "${fpath[1]}/_helm"
    59  `
    60  
    61  const fishCompDesc = `
    62  Generate the autocompletion script for Helm for the fish shell.
    63  
    64  To load completions in your current shell session:
    65  
    66      helm completion fish | source
    67  
    68  To load completions for every new session, execute once:
    69  
    70      helm completion fish > ~/.config/fish/completions/helm.fish
    71  
    72  You will need to start a new shell for this setup to take effect.
    73  `
    74  
    75  const powershellCompDesc = `
    76  Generate the autocompletion script for powershell.
    77  
    78  To load completions in your current shell session:
    79  PS C:\> helm completion powershell | Out-String | Invoke-Expression
    80  
    81  To load completions for every new session, add the output of the above command
    82  to your powershell profile.
    83  `
    84  
    85  const (
    86  	noDescFlagName = "no-descriptions"
    87  	noDescFlagText = "disable completion descriptions"
    88  )
    89  
    90  var disableCompDescriptions bool
    91  
    92  func newCompletionCmd(out io.Writer) *cobra.Command {
    93  	cmd := &cobra.Command{
    94  		Use:   "completion",
    95  		Short: "generate autocompletion scripts for the specified shell",
    96  		Long:  completionDesc,
    97  		Args:  require.NoArgs,
    98  	}
    99  
   100  	bash := &cobra.Command{
   101  		Use:               "bash",
   102  		Short:             "generate autocompletion script for bash",
   103  		Long:              bashCompDesc,
   104  		Args:              require.NoArgs,
   105  		ValidArgsFunction: noCompletions,
   106  		RunE: func(cmd *cobra.Command, args []string) error {
   107  			return runCompletionBash(out, cmd)
   108  		},
   109  	}
   110  	bash.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)
   111  
   112  	zsh := &cobra.Command{
   113  		Use:               "zsh",
   114  		Short:             "generate autocompletion script for zsh",
   115  		Long:              zshCompDesc,
   116  		Args:              require.NoArgs,
   117  		ValidArgsFunction: noCompletions,
   118  		RunE: func(cmd *cobra.Command, args []string) error {
   119  			return runCompletionZsh(out, cmd)
   120  		},
   121  	}
   122  	zsh.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)
   123  
   124  	fish := &cobra.Command{
   125  		Use:               "fish",
   126  		Short:             "generate autocompletion script for fish",
   127  		Long:              fishCompDesc,
   128  		Args:              require.NoArgs,
   129  		ValidArgsFunction: noCompletions,
   130  		RunE: func(cmd *cobra.Command, args []string) error {
   131  			return runCompletionFish(out, cmd)
   132  		},
   133  	}
   134  	fish.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)
   135  
   136  	powershell := &cobra.Command{
   137  		Use:               "powershell",
   138  		Short:             "generate autocompletion script for powershell",
   139  		Long:              powershellCompDesc,
   140  		Args:              require.NoArgs,
   141  		ValidArgsFunction: noCompletions,
   142  		RunE: func(cmd *cobra.Command, args []string) error {
   143  			return runCompletionPowershell(out, cmd)
   144  		},
   145  	}
   146  	powershell.Flags().BoolVar(&disableCompDescriptions, noDescFlagName, false, noDescFlagText)
   147  
   148  	cmd.AddCommand(bash, zsh, fish, powershell)
   149  
   150  	return cmd
   151  }
   152  
   153  func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
   154  	err := cmd.Root().GenBashCompletionV2(out, !disableCompDescriptions)
   155  
   156  	// In case the user renamed the helm binary (e.g., to be able to run
   157  	// both helm2 and helm3), we hook the new binary name to the completion function
   158  	if binary := filepath.Base(os.Args[0]); binary != "helm" {
   159  		renamedBinaryHook := `
   160  # Hook the command used to generate the completion script
   161  # to the helm completion function to handle the case where
   162  # the user renamed the helm binary
   163  if [[ $(type -t compopt) = "builtin" ]]; then
   164      complete -o default -F __start_helm %[1]s
   165  else
   166      complete -o default -o nospace -F __start_helm %[1]s
   167  fi
   168  `
   169  		fmt.Fprintf(out, renamedBinaryHook, binary)
   170  	}
   171  
   172  	return err
   173  }
   174  
   175  func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
   176  	var err error
   177  	if disableCompDescriptions {
   178  		err = cmd.Root().GenZshCompletionNoDesc(out)
   179  	} else {
   180  		err = cmd.Root().GenZshCompletion(out)
   181  	}
   182  
   183  	// In case the user renamed the helm binary (e.g., to be able to run
   184  	// both helm2 and helm3), we hook the new binary name to the completion function
   185  	if binary := filepath.Base(os.Args[0]); binary != "helm" {
   186  		renamedBinaryHook := `
   187  # Hook the command used to generate the completion script
   188  # to the helm completion function to handle the case where
   189  # the user renamed the helm binary
   190  compdef _helm %[1]s
   191  `
   192  		fmt.Fprintf(out, renamedBinaryHook, binary)
   193  	}
   194  
   195  	// Cobra doesn't source zsh completion file, explicitly doing it here
   196  	fmt.Fprintf(out, "compdef _helm helm")
   197  
   198  	return err
   199  }
   200  
   201  func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
   202  	return cmd.Root().GenFishCompletion(out, !disableCompDescriptions)
   203  }
   204  
   205  func runCompletionPowershell(out io.Writer, cmd *cobra.Command) error {
   206  	if disableCompDescriptions {
   207  		return cmd.Root().GenPowerShellCompletion(out)
   208  	}
   209  	return cmd.Root().GenPowerShellCompletionWithDesc(out)
   210  }
   211  
   212  // Function to disable file completion
   213  func noCompletions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
   214  	return nil, cobra.ShellCompDirectiveNoFileComp
   215  }