diff --git a/args.go b/args.go index 70e9b262..6a5554a6 100644 --- a/args.go +++ b/args.go @@ -19,7 +19,7 @@ func legacyArgs(cmd *Command, args []string) error { // root command with subcommands, do subcommand checking. if !cmd.HasParent() && len(args) > 0 { - return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + return cmd.UnknownCommandErrorFunc()(cmd, args[0]) } return nil } diff --git a/command.go b/command.go index 5f1caccc..9767b746 100644 --- a/command.go +++ b/command.go @@ -192,6 +192,8 @@ type Command struct { // flagErrorFunc is func defined by user and it's called when the parsing of // flags returns an error. flagErrorFunc func(*Command, error) error + // unknownCommandErrorFunc is func defined by user, called when the typed command cannot be found + unknownCommandErrorFunc func(*Command, string) error // helpTemplate is help template defined by user. helpTemplate string // helpFunc is help func defined by user. @@ -264,6 +266,12 @@ func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { c.flagErrorFunc = f } +// SetUnknownCommandErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetUnknownCommandErrorFunc(f func(*Command, string) error) { + c.unknownCommandErrorFunc = f +} + // SetHelpFunc sets help function. Can be defined by Application. func (c *Command) SetHelpFunc(f func(*Command, []string)) { c.helpFunc = f @@ -435,6 +443,22 @@ func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { } } +// UnknownCommandErrorFunc returns either the function set by SetUnknownCommandErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) UnknownCommandErrorFunc() (f func(*Command, string) error) { + if c.unknownCommandErrorFunc != nil { + return c.unknownCommandErrorFunc + } + + if c.HasParent() { + return c.parent.unknownCommandErrorFunc + } + return func(c *Command, arg string) error { + return fmt.Errorf("unknown command %q for %q%s", arg, c.CommandPath(), c.findSuggestions(arg)) + } +} + var minUsagePadding = 25 // UsagePadding return padding for the usage. diff --git a/command_test.go b/command_test.go index 16cc41b4..0e88f496 100644 --- a/command_test.go +++ b/command_test.go @@ -1653,6 +1653,28 @@ func TestFlagErrorFunc(t *testing.T) { } } +func TestUnknownCommandErrorFunc(t *testing.T) { + rootCmd := &Command{Use: "root", Run: emptyRun} + subCmd := &Command{ + Use: "type", + Run: emptyRun, + } + rootCmd.AddCommand(subCmd) + + expectedFmt := "unknown command: %v" + rootCmd.SetUnknownCommandErrorFunc(func(_ *Command, arg string) error { + return fmt.Errorf(expectedFmt, arg) + }) + + _, err := executeCommand(rootCmd, "typo") + + got := err.Error() + expected := "unknown command: typo" + if got != expected { + t.Errorf("Expected %v, got %v", expected, got) + } +} + // TestSortedFlags checks, // if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false. // Related to https://github.com/spf13/cobra/issues/404.