Skip to content

Commit

Permalink
Customizable error message prefix (#2023)
Browse files Browse the repository at this point in the history
  • Loading branch information
5ouma committed Sep 8, 2023
1 parent c5dacb3 commit 0c72800
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 2 deletions.
24 changes: 22 additions & 2 deletions command.go
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -595,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 {
Expand Down Expand Up @@ -1050,7 +1070,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
Expand Down Expand Up @@ -1079,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("Error:", err.Error())
c.PrintErrln(cmd.ErrPrefix(), err.Error())
}

// If root command has SilenceUsage flagged,
Expand Down
33 changes: 33 additions & 0 deletions command_test.go
Expand Up @@ -1099,6 +1099,39 @@ func TestShorthandVersionTemplate(t *testing.T) {
checkStringContains(t, output, "customized version: 1.0.0")
}

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, "sub", "--unknown-flag")
if err == nil {
t.Errorf("Expected error")
}

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) {
rootCmd := &Command{Use: "root", Version: "1.0.0"}
rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
Expand Down
6 changes: 6 additions & 0 deletions site/content/user_guide.md
Expand Up @@ -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 receiving 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:
Expand Down

0 comments on commit 0c72800

Please sign in to comment.