diff --git a/README.md b/README.md index b8cda7aab3..3820532e03 100644 --- a/README.md +++ b/README.md @@ -234,11 +234,6 @@ func init() { rootCmd.AddCommand(initCmd) } -func er(msg interface{}) { - fmt.Println("Error:", msg) - os.Exit(1) -} - func initConfig() { if cfgFile != "" { // Use config file from the flag. @@ -246,9 +241,7 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - if err != nil { - er(err) - } + cobra.CheckErr(err) // Search config in home directory with name ".cobra" (without extension). viper.AddConfigPath(home) diff --git a/bash_completions_test.go b/bash_completions_test.go index fc455d8a31..21d1fe0eb8 100644 --- a/bash_completions_test.go +++ b/bash_completions_test.go @@ -51,7 +51,9 @@ func runShellCheck(s string) error { return err } go func() { - stdin.Write([]byte(s)) + _, err := stdin.Write([]byte(s)) + CheckErr(err) + stdin.Close() }() @@ -73,26 +75,26 @@ func TestBashCompletions(t *testing.T) { Run: emptyRun, } rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot") - rootCmd.MarkFlagRequired("introot") + assertNoErr(t, rootCmd.MarkFlagRequired("introot")) // Filename. rootCmd.Flags().String("filename", "", "Enter a filename") - rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml") + assertNoErr(t, rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml")) // Persistent filename. rootCmd.PersistentFlags().String("persistent-filename", "", "Enter a filename") - rootCmd.MarkPersistentFlagFilename("persistent-filename") - rootCmd.MarkPersistentFlagRequired("persistent-filename") + assertNoErr(t, rootCmd.MarkPersistentFlagFilename("persistent-filename")) + assertNoErr(t, rootCmd.MarkPersistentFlagRequired("persistent-filename")) // Filename extensions. rootCmd.Flags().String("filename-ext", "", "Enter a filename (extension limited)") - rootCmd.MarkFlagFilename("filename-ext") + assertNoErr(t, rootCmd.MarkFlagFilename("filename-ext")) rootCmd.Flags().String("custom", "", "Enter a filename (extension limited)") - rootCmd.MarkFlagCustom("custom", "__complete_custom") + assertNoErr(t, rootCmd.MarkFlagCustom("custom", "__complete_custom")) // Subdirectories in a given directory. rootCmd.Flags().String("theme", "", "theme to use (located in /themes/THEMENAME/)") - rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"}) + assertNoErr(t, rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"})) // For two word flags check rootCmd.Flags().StringP("two", "t", "", "this is two word flags") @@ -108,9 +110,9 @@ func TestBashCompletions(t *testing.T) { } echoCmd.Flags().String("filename", "", "Enter a filename") - echoCmd.MarkFlagFilename("filename", "json", "yaml", "yml") + assertNoErr(t, echoCmd.MarkFlagFilename("filename", "json", "yaml", "yml")) echoCmd.Flags().String("config", "", "config to use (located in /config/PROFILE/)") - echoCmd.Flags().SetAnnotation("config", BashCompSubdirsInDir, []string{"config"}) + assertNoErr(t, echoCmd.Flags().SetAnnotation("config", BashCompSubdirsInDir, []string{"config"})) printCmd := &Command{ Use: "print [string to print]", @@ -148,7 +150,7 @@ func TestBashCompletions(t *testing.T) { rootCmd.AddCommand(echoCmd, printCmd, deprecatedCmd, colonCmd) buf := new(bytes.Buffer) - rootCmd.GenBashCompletion(buf) + assertNoErr(t, rootCmd.GenBashCompletion(buf)) output := buf.String() check(t, output, "_root") @@ -215,10 +217,10 @@ func TestBashCompletionHiddenFlag(t *testing.T) { const flagName = "hiddenFlag" c.Flags().Bool(flagName, false, "") - c.Flags().MarkHidden(flagName) + assertNoErr(t, c.Flags().MarkHidden(flagName)) buf := new(bytes.Buffer) - c.GenBashCompletion(buf) + assertNoErr(t, c.GenBashCompletion(buf)) output := buf.String() if strings.Contains(output, flagName) { @@ -231,10 +233,10 @@ func TestBashCompletionDeprecatedFlag(t *testing.T) { const flagName = "deprecated-flag" c.Flags().Bool(flagName, false, "") - c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead") + assertNoErr(t, c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead")) buf := new(bytes.Buffer) - c.GenBashCompletion(buf) + assertNoErr(t, c.GenBashCompletion(buf)) output := buf.String() if strings.Contains(output, flagName) { @@ -249,7 +251,7 @@ func TestBashCompletionTraverseChildren(t *testing.T) { c.Flags().BoolP("bool-flag", "b", false, "bool flag") buf := new(bytes.Buffer) - c.GenBashCompletion(buf) + assertNoErr(t, c.GenBashCompletion(buf)) output := buf.String() // check that local nonpersistent flag are not set since we have TraverseChildren set to true diff --git a/cobra.go b/cobra.go index d01becc8fa..bd7e372cce 100644 --- a/cobra.go +++ b/cobra.go @@ -19,6 +19,7 @@ package cobra import ( "fmt" "io" + "os" "reflect" "strconv" "strings" @@ -205,3 +206,11 @@ func stringInSlice(a string, list []string) bool { } return false } + +// CheckErr prints the msg with the prefix 'Error:' and exits with error code 1. If the msg is nil, it does nothing. +func CheckErr(msg interface{}) { + if msg != nil { + fmt.Fprintln(os.Stderr, "Error:", msg) + os.Exit(1) + } +} diff --git a/cobra/cmd/add.go b/cobra/cmd/add.go index 6645a755f0..8377411edd 100644 --- a/cobra/cmd/add.go +++ b/cobra/cmd/add.go @@ -40,13 +40,11 @@ Example: cobra add server -> resulting in a new cmd/server.go`, Run: func(cmd *cobra.Command, args []string) { if len(args) < 1 { - er("add needs a name for the command") + cobra.CheckErr(fmt.Errorf("add needs a name for the command")) } wd, err := os.Getwd() - if err != nil { - er(err) - } + cobra.CheckErr(err) commandName := validateCmdName(args[0]) command := &Command{ @@ -59,10 +57,7 @@ Example: cobra add server -> resulting in a new cmd/server.go`, }, } - err = command.Create() - if err != nil { - er(err) - } + cobra.CheckErr(command.Create()) fmt.Printf("%s created at %s\n", command.CmdName, command.AbsolutePath) }, @@ -72,7 +67,7 @@ Example: cobra add server -> resulting in a new cmd/server.go`, func init() { addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)") addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command") - addCmd.Flags().MarkDeprecated("package", "this operation has been removed.") + cobra.CheckErr(addCmd.Flags().MarkDeprecated("package", "this operation has been removed.")) } // validateCmdName returns source without any dashes and underscore. diff --git a/cobra/cmd/add_test.go b/cobra/cmd/add_test.go index de92fcea66..0b32ca67e5 100644 --- a/cobra/cmd/add_test.go +++ b/cobra/cmd/add_test.go @@ -14,10 +14,8 @@ func TestGoldenAddCmd(t *testing.T) { } defer os.RemoveAll(command.AbsolutePath) - command.Project.Create() - if err := command.Create(); err != nil { - t.Fatal(err) - } + assertNoErr(t, command.Project.Create()) + assertNoErr(t, command.Create()) generatedFile := fmt.Sprintf("%s/cmd/%s.go", command.AbsolutePath, command.CmdName) goldenFile := fmt.Sprintf("testdata/%s.go.golden", command.CmdName) diff --git a/cobra/cmd/helpers.go b/cobra/cmd/helpers.go index 4a5900d21f..6a8047e38b 100644 --- a/cobra/cmd/helpers.go +++ b/cobra/cmd/helpers.go @@ -14,11 +14,12 @@ package cmd import ( - "fmt" "os" "os/exec" "path/filepath" "strings" + + "github.com/spf13/cobra" ) var srcPaths []string @@ -40,14 +41,12 @@ func init() { } out, err := exec.Command(goExecutable, "env", "GOPATH").Output() - if err != nil { - er(err) - } + cobra.CheckErr(err) toolchainGoPath := strings.TrimSpace(string(out)) goPaths = filepath.SplitList(toolchainGoPath) if len(goPaths) == 0 { - er("$GOPATH is not set") + cobra.CheckErr("$GOPATH is not set") } } srcPaths = make([]string, 0, len(goPaths)) @@ -55,8 +54,3 @@ func init() { srcPaths = append(srcPaths, filepath.Join(goPath, "src")) } } - -func er(msg interface{}) { - fmt.Println("Error:", msg) - os.Exit(1) -} diff --git a/cobra/cmd/helpers_test.go b/cobra/cmd/helpers_test.go new file mode 100644 index 0000000000..c5d20026cf --- /dev/null +++ b/cobra/cmd/helpers_test.go @@ -0,0 +1,9 @@ +package cmd + +import "testing" + +func assertNoErr(t *testing.T, e error) { + if e != nil { + t.Error(e) + } +} diff --git a/cobra/cmd/init.go b/cobra/cmd/init.go index 504a47850e..8c0e617abf 100644 --- a/cobra/cmd/init.go +++ b/cobra/cmd/init.go @@ -39,9 +39,7 @@ and the appropriate structure for a Cobra-based CLI application. Run: func(_ *cobra.Command, args []string) { projectPath, err := initializeProject(args) - if err != nil { - er(err) - } + cobra.CheckErr(err) fmt.Printf("Your Cobra application is ready at\n%s\n", projectPath) }, } @@ -49,7 +47,7 @@ and the appropriate structure for a Cobra-based CLI application. func init() { initCmd.Flags().StringVar(&pkgName, "pkg-name", "", "fully qualified pkg name") - initCmd.MarkFlagRequired("pkg-name") + cobra.CheckErr(initCmd.MarkFlagRequired("pkg-name")) } func initializeProject(args []string) (string, error) { diff --git a/cobra/cmd/init_test.go b/cobra/cmd/init_test.go index c4b3f09a21..6d21ef7730 100644 --- a/cobra/cmd/init_test.go +++ b/cobra/cmd/init_test.go @@ -59,7 +59,7 @@ func TestGoldenInitCmd(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - initCmd.Flags().Set("pkg-name", tt.pkgName) + assertNoErr(t, initCmd.Flags().Set("pkg-name", tt.pkgName)) viper.Set("useViper", true) projectPath, err := initializeProject(tt.args) defer func() { diff --git a/cobra/cmd/licenses.go b/cobra/cmd/licenses.go index a070134ddc..2b3a424389 100644 --- a/cobra/cmd/licenses.go +++ b/cobra/cmd/licenses.go @@ -16,9 +16,11 @@ package cmd import ( + "fmt" "strings" "time" + "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -92,7 +94,7 @@ func copyrightLine() string { func findLicense(name string) License { found := matchLicense(name) if found == "" { - er("unknown license: " + name) + cobra.CheckErr(fmt.Errorf("unknown license: " + name)) } return Licenses[found] } diff --git a/cobra/cmd/project.go b/cobra/cmd/project.go index ecd783d030..bd68a31d78 100644 --- a/cobra/cmd/project.go +++ b/cobra/cmd/project.go @@ -5,6 +5,7 @@ import ( "os" "text/template" + "github.com/spf13/cobra" "github.com/spf13/cobra/cobra/tpl" ) @@ -49,7 +50,7 @@ func (p *Project) Create() error { // create cmd/root.go if _, err = os.Stat(fmt.Sprintf("%s/cmd", p.AbsolutePath)); os.IsNotExist(err) { - os.Mkdir(fmt.Sprintf("%s/cmd", p.AbsolutePath), 0751) + cobra.CheckErr(os.Mkdir(fmt.Sprintf("%s/cmd", p.AbsolutePath), 0751)) } rootFile, err := os.Create(fmt.Sprintf("%s/cmd/root.go", p.AbsolutePath)) if err != nil { diff --git a/cobra/cmd/root.go b/cobra/cmd/root.go index 97f404bbb6..f27ae7e6cf 100644 --- a/cobra/cmd/root.go +++ b/cobra/cmd/root.go @@ -47,8 +47,8 @@ func init() { rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution") rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project") rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) + cobra.CheckErr(viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))) + cobra.CheckErr(viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))) viper.SetDefault("author", "NAME HERE ") viper.SetDefault("license", "apache") @@ -63,9 +63,7 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - if err != nil { - er(err) - } + cobra.CheckErr(err) // Search config in home directory with name ".cobra" (without extension). viper.AddConfigPath(home) diff --git a/cobra/cmd/testdata/root.go.golden b/cobra/cmd/testdata/root.go.golden index 9a554a7c13..dba491123b 100644 --- a/cobra/cmd/testdata/root.go.golden +++ b/cobra/cmd/testdata/root.go.golden @@ -44,10 +44,7 @@ to quickly create a Cobra application.`, // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } + cobra.CheckErr(rootCmd.Execute()) } func init() { @@ -72,10 +69,7 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } + cobra.CheckErr(err) // Search config in home directory with name ".testproject" (without extension). viper.AddConfigPath(home) diff --git a/cobra/tpl/main.go b/cobra/tpl/main.go index 59daa00bfc..0b9c6610e3 100644 --- a/cobra/tpl/main.go +++ b/cobra/tpl/main.go @@ -53,10 +53,7 @@ to quickly create a Cobra application.` + "`" + `, // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } + cobra.CheckErr(rootCmd.Execute()) } func init() { @@ -85,10 +82,7 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } + cobra.CheckErr(err) // Search config in home directory with name ".{{ .AppName }}" (without extension). viper.AddConfigPath(home) diff --git a/cobra_test.go b/cobra_test.go index 0d1755bdba..1219cc0792 100644 --- a/cobra_test.go +++ b/cobra_test.go @@ -5,6 +5,12 @@ import ( "text/template" ) +func assertNoErr(t *testing.T, e error) { + if e != nil { + t.Error(e) + } +} + func TestAddTemplateFunctions(t *testing.T) { AddTemplateFunc("t", func() bool { return true }) AddTemplateFuncs(template.FuncMap{ diff --git a/command.go b/command.go index 42d2ced42c..9c58006e10 100644 --- a/command.go +++ b/command.go @@ -420,7 +420,7 @@ func (c *Command) UsageString() string { c.outWriter = bb c.errWriter = bb - c.Usage() + CheckErr(c.Usage()) // Setting things back to normal c.outWriter = tmpOutput @@ -1089,10 +1089,10 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`, cmd, _, e := c.Root().Find(args) if cmd == nil || e != nil { c.Printf("Unknown help topic %#q\n", args) - c.Root().Usage() + CheckErr(c.Root().Usage()) } else { cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown - cmd.Help() + CheckErr(cmd.Help()) } }, } diff --git a/command_test.go b/command_test.go index 924228db42..9640fc5dce 100644 --- a/command_test.go +++ b/command_test.go @@ -737,9 +737,9 @@ func TestPersistentFlagsOnChild(t *testing.T) { func TestRequiredFlags(t *testing.T) { c := &Command{Use: "c", Run: emptyRun} c.Flags().String("foo1", "", "") - c.MarkFlagRequired("foo1") + assertNoErr(t, c.MarkFlagRequired("foo1")) c.Flags().String("foo2", "", "") - c.MarkFlagRequired("foo2") + assertNoErr(t, c.MarkFlagRequired("foo2")) c.Flags().String("bar", "", "") expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2") @@ -755,16 +755,16 @@ func TestRequiredFlags(t *testing.T) { func TestPersistentRequiredFlags(t *testing.T) { parent := &Command{Use: "parent", Run: emptyRun} parent.PersistentFlags().String("foo1", "", "") - parent.MarkPersistentFlagRequired("foo1") + assertNoErr(t, parent.MarkPersistentFlagRequired("foo1")) parent.PersistentFlags().String("foo2", "", "") - parent.MarkPersistentFlagRequired("foo2") + assertNoErr(t, parent.MarkPersistentFlagRequired("foo2")) parent.Flags().String("foo3", "", "") child := &Command{Use: "child", Run: emptyRun} child.Flags().String("bar1", "", "") - child.MarkFlagRequired("bar1") + assertNoErr(t, child.MarkFlagRequired("bar1")) child.Flags().String("bar2", "", "") - child.MarkFlagRequired("bar2") + assertNoErr(t, child.MarkFlagRequired("bar2")) child.Flags().String("bar3", "", "") parent.AddCommand(child) @@ -784,7 +784,7 @@ func TestPersistentRequiredFlagsWithDisableFlagParsing(t *testing.T) { parent := &Command{Use: "parent", Run: emptyRun} parent.PersistentFlags().Bool("foo", false, "") flag := parent.PersistentFlags().Lookup("foo") - parent.MarkPersistentFlagRequired("foo") + assertNoErr(t, parent.MarkPersistentFlagRequired("foo")) child := &Command{Use: "child", Run: emptyRun} child.DisableFlagParsing = true @@ -1729,7 +1729,7 @@ func TestMergeCommandLineToFlags(t *testing.T) { func TestUseDeprecatedFlags(t *testing.T) { c := &Command{Use: "c", Run: emptyRun} c.Flags().BoolP("deprecated", "d", false, "deprecated flag") - c.Flags().MarkDeprecated("deprecated", "This flag is deprecated") + assertNoErr(t, c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")) output, err := executeCommand(c, "c", "-d") if err != nil { @@ -1877,7 +1877,7 @@ func (tc *calledAsTestcase) test(t *testing.T) { parent.SetOut(output) parent.SetErr(output) - parent.Execute() + _ = parent.Execute() if called == nil { if tc.call != "" { diff --git a/custom_completions.go b/custom_completions.go index f9e88e081f..d1ee694840 100644 --- a/custom_completions.go +++ b/custom_completions.go @@ -527,13 +527,14 @@ func CompDebug(msg string, printToStdErr bool) { os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err == nil { defer f.Close() - f.WriteString(msg) + _, err := f.WriteString(msg) + CheckErr(err) } } if printToStdErr { // Must print to stderr for this not to be read by the completion script. - fmt.Fprintf(os.Stderr, msg) + fmt.Fprint(os.Stderr, msg) } } diff --git a/custom_completions_test.go b/custom_completions_test.go index 14ec5a9eb6..ede809ed43 100644 --- a/custom_completions_test.go +++ b/custom_completions_test.go @@ -780,17 +780,17 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { rootCmd.AddCommand(childCmd) rootCmd.Flags().IntP("requiredFlag", "r", -1, "required flag") - rootCmd.MarkFlagRequired("requiredFlag") + assertNoErr(t, rootCmd.MarkFlagRequired("requiredFlag")) requiredFlag := rootCmd.Flags().Lookup("requiredFlag") rootCmd.PersistentFlags().IntP("requiredPersistent", "p", -1, "required persistent") - rootCmd.MarkPersistentFlagRequired("requiredPersistent") + assertNoErr(t, rootCmd.MarkPersistentFlagRequired("requiredPersistent")) requiredPersistent := rootCmd.PersistentFlags().Lookup("requiredPersistent") rootCmd.Flags().StringP("release", "R", "", "Release name") childCmd.Flags().BoolP("subRequired", "s", false, "sub required flag") - childCmd.MarkFlagRequired("subRequired") + assertNoErr(t, childCmd.MarkFlagRequired("subRequired")) childCmd.Flags().BoolP("subNotRequired", "n", false, "sub not required flag") // Test that a required flag is suggested even without the - prefix @@ -964,19 +964,19 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { // No extensions. Should be ignored. rootCmd.Flags().StringP("file", "f", "", "file flag") - rootCmd.MarkFlagFilename("file") + assertNoErr(t, rootCmd.MarkFlagFilename("file")) // Single extension rootCmd.Flags().StringP("log", "l", "", "log flag") - rootCmd.MarkFlagFilename("log", "log") + assertNoErr(t, rootCmd.MarkFlagFilename("log", "log")) // Multiple extensions rootCmd.Flags().StringP("yaml", "y", "", "yaml flag") - rootCmd.MarkFlagFilename("yaml", "yaml", "yml") + assertNoErr(t, rootCmd.MarkFlagFilename("yaml", "yaml", "yml")) // Directly using annotation rootCmd.Flags().StringP("text", "t", "", "text flag") - rootCmd.Flags().SetAnnotation("text", BashCompFilenameExt, []string{"txt"}) + assertNoErr(t, rootCmd.Flags().SetAnnotation("text", BashCompFilenameExt, []string{"txt"})) // Test that the completion logic returns the proper info for the completion // script to handle the file filtering @@ -1086,15 +1086,15 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { // Filter directories rootCmd.Flags().StringP("dir", "d", "", "dir flag") - rootCmd.MarkFlagDirname("dir") + assertNoErr(t, rootCmd.MarkFlagDirname("dir")) // Filter directories within a directory rootCmd.Flags().StringP("subdir", "s", "", "subdir") - rootCmd.Flags().SetAnnotation("subdir", BashCompSubdirsInDir, []string{"themes"}) + assertNoErr(t, rootCmd.Flags().SetAnnotation("subdir", BashCompSubdirsInDir, []string{"themes"})) // Multiple directory specification get ignored rootCmd.Flags().StringP("manydir", "m", "", "manydir") - rootCmd.Flags().SetAnnotation("manydir", BashCompSubdirsInDir, []string{"themes", "colors"}) + assertNoErr(t, rootCmd.Flags().SetAnnotation("manydir", BashCompSubdirsInDir, []string{"themes", "colors"})) // Test that the completion logic returns the proper info for the completion // script to handle the directory filtering @@ -1430,7 +1430,7 @@ func TestValidArgsFuncInBashScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenBashCompletion(buf) + assertNoErr(t, rootCmd.GenBashCompletion(buf)) output := buf.String() check(t, output, "has_completion_function=1") @@ -1445,7 +1445,7 @@ func TestNoValidArgsFuncInBashScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenBashCompletion(buf) + assertNoErr(t, rootCmd.GenBashCompletion(buf)) output := buf.String() checkOmit(t, output, "has_completion_function=1") @@ -1461,7 +1461,7 @@ func TestCompleteCmdInBashScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenBashCompletion(buf) + assertNoErr(t, rootCmd.GenBashCompletion(buf)) output := buf.String() check(t, output, ShellCompNoDescRequestCmd) @@ -1477,7 +1477,7 @@ func TestCompleteNoDesCmdInZshScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenZshCompletionNoDesc(buf) + assertNoErr(t, rootCmd.GenZshCompletionNoDesc(buf)) output := buf.String() check(t, output, ShellCompNoDescRequestCmd) @@ -1493,7 +1493,7 @@ func TestCompleteCmdInZshScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenZshCompletion(buf) + assertNoErr(t, rootCmd.GenZshCompletion(buf)) output := buf.String() check(t, output, ShellCompRequestCmd) @@ -1506,7 +1506,7 @@ func TestFlagCompletionInGo(t *testing.T) { Run: emptyRun, } rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot") - rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { completions := []string{} for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} { if strings.HasPrefix(comp, toComplete) { @@ -1514,9 +1514,9 @@ func TestFlagCompletionInGo(t *testing.T) { } } return completions, ShellCompDirectiveDefault - }) + })) rootCmd.Flags().String("filename", "", "Enter a filename") - rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { completions := []string{} for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} { if strings.HasPrefix(comp, toComplete) { @@ -1524,7 +1524,7 @@ func TestFlagCompletionInGo(t *testing.T) { } } return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp - }) + })) // Test completing an empty string output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--introot", "") @@ -1703,7 +1703,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { Run: emptyRun, } rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot") - rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { completions := []string{} for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} { if strings.HasPrefix(comp, toComplete) { @@ -1711,9 +1711,9 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { } } return completions, ShellCompDirectiveDefault - }) + })) rootCmd.Flags().String("filename", "", "Enter a filename") - rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { completions := []string{} for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} { if strings.HasPrefix(comp, toComplete) { @@ -1721,7 +1721,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { } } return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp - }) + })) // Test completing an empty string output, err := executeCommand(rootCmd, ShellCompRequestCmd, "--introot", "") diff --git a/doc/man_docs_test.go b/doc/man_docs_test.go index ee9b87535a..aa3f5f2a18 100644 --- a/doc/man_docs_test.go +++ b/doc/man_docs_test.go @@ -13,6 +13,12 @@ import ( "github.com/spf13/cobra" ) +func assertNoErr(t *testing.T, e error) { + if e != nil { + t.Error(e) + } +} + func translate(in string) string { return strings.Replace(in, "-", "\\-", -1) } @@ -133,7 +139,7 @@ func TestGenManSeeAlso(t *testing.T) { func TestManPrintFlagsHidesShortDeperecated(t *testing.T) { c := &cobra.Command{} c.Flags().StringP("foo", "f", "default", "Foo flag") - c.Flags().MarkShorthandDeprecated("foo", "don't use it no more") + assertNoErr(t, c.Flags().MarkShorthandDeprecated("foo", "don't use it no more")) buf := new(bytes.Buffer) manPrintFlags(buf, c.Flags()) diff --git a/doc/man_examples_test.go b/doc/man_examples_test.go index db6604268a..e20a34c38e 100644 --- a/doc/man_examples_test.go +++ b/doc/man_examples_test.go @@ -17,7 +17,7 @@ func ExampleGenManTree() { Title: "MINE", Section: "3", } - doc.GenManTree(cmd, header, "/tmp") + cobra.CheckErr(doc.GenManTree(cmd, header, "/tmp")) } func ExampleGenMan() { @@ -30,6 +30,6 @@ func ExampleGenMan() { Section: "3", } out := new(bytes.Buffer) - doc.GenMan(cmd, header, out) + cobra.CheckErr(doc.GenMan(cmd, header, out)) fmt.Print(out.String()) } diff --git a/fish_completions_test.go b/fish_completions_test.go index 532b6055a7..a3171e481e 100644 --- a/fish_completions_test.go +++ b/fish_completions_test.go @@ -15,7 +15,7 @@ func TestCompleteNoDesCmdInFishScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, false) + assertNoErr(t, rootCmd.GenFishCompletion(buf, false)) output := buf.String() check(t, output, ShellCompNoDescRequestCmd) @@ -31,7 +31,7 @@ func TestCompleteCmdInFishScript(t *testing.T) { rootCmd.AddCommand(child) buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, true) + assertNoErr(t, rootCmd.GenFishCompletion(buf, true)) output := buf.String() check(t, output, ShellCompRequestCmd) @@ -41,7 +41,7 @@ func TestCompleteCmdInFishScript(t *testing.T) { func TestProgWithDash(t *testing.T) { rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun} buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, false) + assertNoErr(t, rootCmd.GenFishCompletion(buf, false)) output := buf.String() // Functions name should have replace the '-' @@ -56,7 +56,7 @@ func TestProgWithDash(t *testing.T) { func TestProgWithColon(t *testing.T) { rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun} buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, false) + assertNoErr(t, rootCmd.GenFishCompletion(buf, false)) output := buf.String() // Functions name should have replace the ':' diff --git a/powershell_completions_test.go b/powershell_completions_test.go index 29b609de05..30b354b4b5 100644 --- a/powershell_completions_test.go +++ b/powershell_completions_test.go @@ -109,7 +109,7 @@ func TestPowerShellCompletion(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { buf := new(bytes.Buffer) - tc.root.GenPowerShellCompletion(buf) + assertNoErr(t, tc.root.GenPowerShellCompletion(buf)) output := buf.String() for _, expectedExpression := range tc.expectedExpressions { diff --git a/shell_completions.md b/shell_completions.md index d8416ab1dc..91ce7724c7 100644 --- a/shell_completions.md +++ b/shell_completions.md @@ -91,8 +91,7 @@ cmd := &cobra.Command{ Long: get_long, Example: get_example, Run: func(cmd *cobra.Command, args []string) { - err := RunGet(f, out, cmd, args) - util.CheckErr(err) + cobra.CheckErr(RunGet(f, out, cmd, args)) }, ValidArgs: validArgs, } @@ -124,7 +123,7 @@ the completion algorithm if entered manually, e.g. in: ```bash $ kubectl get rc [tab][tab] -backend frontend database +backend frontend database ``` Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of @@ -246,7 +245,7 @@ and you'll get something like ```bash $ kubectl exec [tab][tab] --c --container= -p --pod= +-c --container= -p --pod= ``` ### Specify dynamic flag completion