diff --git a/app.go b/app.go index 41b08a8..46a699e 100644 --- a/app.go +++ b/app.go @@ -8,6 +8,11 @@ import ( "time" ) +var ( + // Set to 125 which is the highest number not used in most shells + DefaultExitCode int = 0 +) + // App is the main structure of a cli application. It is recomended that // an app be created with the cli.NewApp() function type App struct { @@ -77,7 +82,7 @@ func NewApp() *App { } // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination -func (a *App) Run(arguments []string) (err error) { +func (a *App) Run(arguments []string) (ec int, err error) { if a.Author != "" || a.Email != "" { a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) } @@ -108,7 +113,7 @@ func (a *App) Run(arguments []string) (err error) { fmt.Fprintln(a.Writer, nerr) context := NewContext(a, set, nil) ShowAppHelp(context) - return nerr + return DefaultExitCode, nerr } context := NewContext(a, set, nil) @@ -116,24 +121,24 @@ func (a *App) Run(arguments []string) (err error) { fmt.Fprintln(a.Writer, "Incorrect Usage.") fmt.Fprintln(a.Writer) ShowAppHelp(context) - return err + return DefaultExitCode, err } if checkCompletions(context) { - return nil + return 0, nil } if checkHelp(context) { - return nil + return 0, nil } if checkVersion(context) { - return nil + return 0, nil } if a.After != nil { defer func() { - afterErr := a.After(context) + afterEc, afterErr := a.After(context) if afterErr != nil { if err != nil { err = NewMultiError(err, afterErr) @@ -141,13 +146,14 @@ func (a *App) Run(arguments []string) (err error) { err = afterErr } } + ec = afterEc }() } if a.Before != nil { - err := a.Before(context) + ec, err = a.Before(context) if err != nil { - return err + return ec, err } } @@ -161,20 +167,19 @@ func (a *App) Run(arguments []string) (err error) { } // Run default Action - a.Action(context) - return nil + return a.Action(context), nil } // Another entry point to the cli app, takes care of passing arguments and error handling func (a *App) RunAndExitOnError() { - if err := a.Run(os.Args); err != nil { + if exitCode, err := a.Run(os.Args); err != nil { fmt.Fprintln(os.Stderr, err) - os.Exit(1) + os.Exit(exitCode) } } // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags -func (a *App) RunAsSubcommand(ctx *Context) (err error) { +func (a *App) RunAsSubcommand(ctx *Context) (ec int, err error) { // append help to commands if len(a.Commands) > 0 { if a.Command(helpCommand.Name) == nil && !a.HideHelp { @@ -205,33 +210,33 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } else { ShowCommandHelp(ctx, context.Args().First()) } - return nerr + return DefaultExitCode, nerr } if err != nil { fmt.Fprintln(a.Writer, "Incorrect Usage.") fmt.Fprintln(a.Writer) ShowSubcommandHelp(context) - return err + return DefaultExitCode, err } if checkCompletions(context) { - return nil + return 0, nil } if len(a.Commands) > 0 { if checkSubcommandHelp(context) { - return nil + return 0, nil } } else { if checkCommandHelp(ctx, context.Args().First()) { - return nil + return 0, nil } } if a.After != nil { defer func() { - afterErr := a.After(context) + afterEc, afterErr := a.After(context) if afterErr != nil { if err != nil { err = NewMultiError(err, afterErr) @@ -239,13 +244,14 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { err = afterErr } } + ec = afterEc }() } if a.Before != nil { - err := a.Before(context) + ec, err = a.Before(context) if err != nil { - return err + return ec, err } } @@ -259,9 +265,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } // Run default Action - a.Action(context) - - return nil + return a.Action(context), nil } // Returns the named command on App. Returns nil if the command does not exist diff --git a/command.go b/command.go index 7022f8c..9aa42db 100644 --- a/command.go +++ b/command.go @@ -50,7 +50,7 @@ func (c Command) FullName() string { } // Invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c Command) Run(ctx *Context) error { +func (c Command) Run(ctx *Context) (int, error) { if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { return c.startApp(ctx) } @@ -104,7 +104,7 @@ func (c Command) Run(ctx *Context) error { fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.") fmt.Fprintln(ctx.App.Writer) ShowCommandHelp(ctx, c.Name) - return err + return DefaultExitCode, err } nerr := normalizeFlags(c.Flags, set) @@ -112,20 +112,19 @@ func (c Command) Run(ctx *Context) error { fmt.Fprintln(ctx.App.Writer, nerr) fmt.Fprintln(ctx.App.Writer) ShowCommandHelp(ctx, c.Name) - return nerr + return DefaultExitCode, nerr } context := NewContext(ctx.App, set, ctx) if checkCommandCompletions(context, c.Name) { - return nil + return 0, nil } if checkCommandHelp(context, c.Name) { - return nil + return 0, nil } context.Command = c - c.Action(context) - return nil + return c.Action(context), nil } func (c Command) Names() []string { @@ -148,7 +147,7 @@ func (c Command) HasName(name string) bool { return false } -func (c Command) startApp(ctx *Context) error { +func (c Command) startApp(ctx *Context) (int, error) { app := NewApp() // set the name and usage diff --git a/funcs.go b/funcs.go index 6807c98..48909c1 100644 --- a/funcs.go +++ b/funcs.go @@ -5,14 +5,14 @@ type BashCompleteFn func(*Context) // An action to execute before any subcommands are run, but after the context is ready // If a non-nil error is returned, no subcommands are run -type BeforeFn func(*Context) error +type BeforeFn func(*Context) (int, error) // An action to execute after any subcommands are run, but after the subcommand has finished // It is run even if Action() panics -type AfterFn func(*Context) error +type AfterFn func(*Context) (int, error) // The action to execute when no subcommands are specified -type ActionFn func(*Context) +type ActionFn func(*Context) int // Execute this function if the proper command cannot be found type CommandNotFoundFn func(*Context, string) diff --git a/help.go b/help.go index 66ef2fb..e1faef6 100644 --- a/help.go +++ b/help.go @@ -72,13 +72,14 @@ var helpCommand = Command{ Name: "help", Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", - Action: func(c *Context) { + Action: func(c *Context) int { args := c.Args() if args.Present() { ShowCommandHelp(c, args.First()) } else { ShowAppHelp(c) } + return 0 }, } @@ -86,13 +87,14 @@ var helpSubcommand = Command{ Name: "help", Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", - Action: func(c *Context) { + Action: func(c *Context) int { args := c.Args() if args.Present() { ShowCommandHelp(c, args.First()) } else { ShowSubcommandHelp(c) } + return 0 }, }