From 48dabba4d3133af67e2edcc2be80af2fd9f3d7fd Mon Sep 17 00:00:00 2001 From: Souma <101255979+5ouma@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:33:06 +0900 Subject: [PATCH 1/8] [add] The error message prefix The user can change it by specifying `errPrefix` by `SetErrPrefix`. --- command.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/command.go b/command.go index e4945ab84..3d30a53ca 100644 --- a/command.go +++ b/command.go @@ -181,6 +181,9 @@ type Command struct { // versionTemplate is the version template defined by user. versionTemplate string + // errPrefix is the error message prefix defined by user. + errPrefix string + // inReader is a reader defined by the user that replaces stdin inReader io.Reader // outWriter is a writer defined by the user that replaces stdout @@ -346,6 +349,11 @@ func (c *Command) SetVersionTemplate(s string) { c.versionTemplate = s } +// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. +func (c *Command) SetErrPrefix(s string) { + c.errPrefix = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -1050,7 +1058,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(c.errPrefix, err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err @@ -1079,7 +1087,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(c.errPrefix, err.Error()) } // If root command has SilenceUsage flagged, From ff58b537c7652fc4234649958771f7d57ea8ae41 Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Thu, 31 Aug 2023 21:39:37 +0900 Subject: [PATCH 2/8] [update] Use the prefix, `Error:` by default If there's no specifying, return the prefix used before. --- command.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/command.go b/command.go index 3d30a53ca..7f0363071 100644 --- a/command.go +++ b/command.go @@ -603,6 +603,18 @@ func (c *Command) VersionTemplate() string { ` } +// ErrPrefix return error message prefix for the command +func (c *Command) ErrPrefix() string { + if c.errPrefix != "" { + return c.errPrefix + } + + if c.HasParent() { + return c.parent.ErrPrefix() + } + return "Error:" +} + func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { flag := fs.Lookup(name) if flag == nil { @@ -1058,7 +1070,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln(c.errPrefix, err.Error()) + c.PrintErrln(c.ErrPrefix(), err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err @@ -1087,7 +1099,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.PrintErrln(c.errPrefix, err.Error()) + c.PrintErrln(c.ErrPrefix(), err.Error()) } // If root command has SilenceUsage flagged, From a76559e04a52ad85993dfe276b91591ad54c4b76 Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:06:32 +0900 Subject: [PATCH 3/8] [update] Doc to use `errPrefix` Description to change it and what it is. --- site/content/user_guide.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/site/content/user_guide.md b/site/content/user_guide.md index 56e8e44a3..03972bb99 100644 --- a/site/content/user_guide.md +++ b/site/content/user_guide.md @@ -596,6 +596,12 @@ Running an application with the '--version' flag will print the version to stdou the version template. The template can be customized using the `cmd.SetVersionTemplate(s string)` function. +## Error Message Prefix + +Cobra prints an error message when being returned a non-nil error value. +The default error message is `Error: error contents`. +The Prefix, `Error:` can be customized using the `cmd.SetErrPrefix(s string)` function. + ## PreRun and PostRun Hooks It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: From da3c9eeebd0302584ccc2031a8ab917779d04ce9 Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Fri, 1 Sep 2023 15:31:11 +0900 Subject: [PATCH 4/8] [update] Test for `SetErrPrefix()` If it doesn't output any errors, fails the test. --- command_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/command_test.go b/command_test.go index b0f5e860e..d234b3558 100644 --- a/command_test.go +++ b/command_test.go @@ -1099,6 +1099,18 @@ func TestShorthandVersionTemplate(t *testing.T) { checkStringContains(t, output, "customized version: 1.0.0") } +func TestErrPrefix(t *testing.T) { + rootCmd := &Command{Use: "root", SilenceUsage: true, Run: emptyRun} + rootCmd.SetErrPrefix("customized error prefix:") + + output, err := executeCommand(rootCmd, "--unknown", "flag") + if err == nil { + t.Errorf("Expected error") + } + + checkStringContains(t, output, "customized error prefix: unknown flag: --unknown") +} + func TestVersionFlagExecutedOnSubcommand(t *testing.T) { rootCmd := &Command{Use: "root", Version: "1.0.0"} rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun}) From fabc43c5eb01771416e69f31ff874e59d8594fa6 Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Fri, 8 Sep 2023 11:32:04 +0900 Subject: [PATCH 5/8] [update] Several changes that were reviewed Fix some grammar misses and use `cmd` for subcommands. --- command.go | 2 +- site/content/user_guide.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/command.go b/command.go index 7f0363071..6866f7d0f 100644 --- a/command.go +++ b/command.go @@ -1099,7 +1099,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.PrintErrln(c.ErrPrefix(), err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) } // If root command has SilenceUsage flagged, diff --git a/site/content/user_guide.md b/site/content/user_guide.md index 03972bb99..93daadf56 100644 --- a/site/content/user_guide.md +++ b/site/content/user_guide.md @@ -598,8 +598,8 @@ the version template. The template can be customized using the ## Error Message Prefix -Cobra prints an error message when being returned a non-nil error value. -The default error message is `Error: error contents`. +Cobra prints an error message when receiving a non-nil error value. +The default error message is `Error: `. The Prefix, `Error:` can be customized using the `cmd.SetErrPrefix(s string)` function. ## PreRun and PostRun Hooks From ed4583eb5930ed9234835c7b00a11eee99ee3f0c Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Fri, 8 Sep 2023 12:10:16 +0900 Subject: [PATCH 6/8] [update] More tests that were requested Root error prefix called from subcommand, and different error prefixes in root and subcommand. https://github.com/spf13/cobra/pull/2023#discussion_r1319266611 --- command_test.go | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/command_test.go b/command_test.go index d234b3558..4afb7f7b8 100644 --- a/command_test.go +++ b/command_test.go @@ -1099,16 +1099,37 @@ func TestShorthandVersionTemplate(t *testing.T) { checkStringContains(t, output, "customized version: 1.0.0") } -func TestErrPrefix(t *testing.T) { - rootCmd := &Command{Use: "root", SilenceUsage: true, Run: emptyRun} - rootCmd.SetErrPrefix("customized error prefix:") +func TestRootErrPrefixExecutedOnSubcommand(t *testing.T) { + rootCmd := &Command{Use: "root", Run: emptyRun} + rootCmd.SetErrPrefix("root error prefix:") + rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun}) - output, err := executeCommand(rootCmd, "--unknown", "flag") + output, err := executeCommand(rootCmd, "sub", "--unknown-flag") if err == nil { t.Errorf("Expected error") } - checkStringContains(t, output, "customized error prefix: unknown flag: --unknown") + checkStringContains(t, output, "root error prefix: unknown flag: --unknown-flag") +} + +func TestRootAndSubErrPrefix(t *testing.T) { + rootCmd := &Command{Use: "root", Run: emptyRun} + subCmd := &Command{Use: "sub", Run: emptyRun} + rootCmd.AddCommand(subCmd) + rootCmd.SetErrPrefix("root error prefix:") + subCmd.SetErrPrefix("sub error prefix:") + + if output, err := executeCommand(rootCmd, "--unknown-root-flag"); err == nil { + t.Errorf("Expected error") + } else { + checkStringContains(t, output, "root error prefix: unknown flag: --unknown-root-flag") + } + + if output, err := executeCommand(rootCmd, "sub", "--unknown-sub-flag"); err == nil { + t.Errorf("Expected error") + } else { + checkStringContains(t, output, "sub error prefix: unknown flag: --unknown-sub-flag") + } } func TestVersionFlagExecutedOnSubcommand(t *testing.T) { From 5dec565c9024ad758fa7808602f2cd2a282c581e Mon Sep 17 00:00:00 2001 From: Souma <101255979+5ouma@users.noreply.github.com> Date: Fri, 8 Sep 2023 18:12:05 +0900 Subject: [PATCH 7/8] [fix] Forgot to change `c.ErrPrefix()` to `cmd.ErrPrefix()` To use an error prefix of subcommand as well. --- command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command.go b/command.go index 6866f7d0f..523cb57e2 100644 --- a/command.go +++ b/command.go @@ -1070,7 +1070,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln(c.ErrPrefix(), err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err From c24c3fdecf45a0378f8ffdf07f3a8c8e82f0a371 Mon Sep 17 00:00:00 2001 From: 5ouma <101255979+5ouma@users.noreply.github.com> Date: Fri, 8 Sep 2023 21:36:58 +0900 Subject: [PATCH 8/8] [revert] Crude change of `c.ErrPrefix()` Since `cmd` is `nil` or same as `c`. --- command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command.go b/command.go index 523cb57e2..6866f7d0f 100644 --- a/command.go +++ b/command.go @@ -1070,7 +1070,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln(cmd.ErrPrefix(), err.Error()) + c.PrintErrln(c.ErrPrefix(), err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err