diff --git a/command.go b/command.go index d7d37ac1..0668560a 100644 --- a/command.go +++ b/command.go @@ -23,11 +23,13 @@ import ( "os" "path/filepath" "sort" - "strings" flag "github.com/spf13/pflag" + "strings" ) +var NotRunnable = errors.New("Command not runnable; need subcommand.") + // Command is just that, a command for your application. // E.g. 'go run ...' - 'run' is the command. Cobra requires // you to define the usage and description as part of your command @@ -714,7 +716,7 @@ func (c *Command) execute(a []string) (err error) { } if !c.Runnable() { - return errors.New("Subcommand required.") + return NotRunnable } c.preRun() @@ -850,6 +852,14 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { return cmd, nil } + // If command wasn't runnable, show full help, but do return the error. + // This will result in apps by default returning a non-success exit code, but also gives them the option to + // handle specially. + if err == NotRunnable { + cmd.HelpFunc()(cmd, args) + return cmd, err + } + // If root command has SilentErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { diff --git a/command_test.go b/command_test.go index d874a9a5..c1b87496 100644 --- a/command_test.go +++ b/command_test.go @@ -836,8 +836,8 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) { rootCmd.AddCommand(childCmd) output, err := executeCommand(rootCmd, "child") - if err != nil { - t.Errorf("Unexpected error: %v", err) + if err != NotRunnable { + t.Error("Expected error for missing subcommand.") } checkStringContains(t, output, childCmd.Long)