* Added ability to customize usage error messages

main
Gregor Noczinski 9 years ago
parent f9cc3001e0
commit 7319f042e4

@ -44,6 +44,10 @@ type App struct {
Action func(context *Context) Action func(context *Context)
// Execute this function if the proper command cannot be found // Execute this function if the proper command cannot be found
CommandNotFound func(context *Context, command string) CommandNotFound func(context *Context, command string)
// Execute this function if an usage error occurs. This is useful for displaying customized usage error messages.
// This function is able to manipulate the original error in another.
// If this function is not set the "Incorrect usage" is displayed and the execution is interrupted.
OnUsageError func(context *Context, err error, isSubcommand bool) error
// Compilation date // Compilation date
Compiled time.Time Compiled time.Time
// List of all authors who contributed // List of all authors who contributed
@ -132,10 +136,15 @@ func (a *App) Run(arguments []string) (err error) {
} }
if err != nil { if err != nil {
fmt.Fprintln(a.Writer, "Incorrect Usage.") if a.OnUsageError != nil {
fmt.Fprintln(a.Writer) err := a.OnUsageError(context, err, false)
ShowAppHelp(context) return err
return err } else {
fmt.Fprintln(a.Writer, "Incorrect Usage.")
fmt.Fprintln(a.Writer)
ShowAppHelp(context)
return err
}
} }
if !a.HideHelp && checkHelp(context) { if !a.HideHelp && checkHelp(context) {
@ -242,10 +251,15 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
} }
if err != nil { if err != nil {
fmt.Fprintln(a.Writer, "Incorrect Usage.") if a.OnUsageError != nil {
fmt.Fprintln(a.Writer) err = a.OnUsageError(context, err, true)
ShowSubcommandHelp(context) return err
return err } else {
fmt.Fprintln(a.Writer, "Incorrect Usage.")
fmt.Fprintln(a.Writer)
ShowSubcommandHelp(context)
return err
}
} }
if len(a.Commands) > 0 { if len(a.Commands) > 0 {

@ -9,6 +9,7 @@ import (
"os" "os"
"strings" "strings"
"testing" "testing"
"errors"
) )
func ExampleApp_Run() { func ExampleApp_Run() {
@ -965,3 +966,63 @@ func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
t.Errorf("expected text of error from After method, but got none in \"%v\"", err) t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
} }
} }
func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) {
app := NewApp()
app.Flags = []Flag{
IntFlag{Name: "flag"},
}
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
if isSubcommand {
t.Errorf("Expect no subcommand")
}
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err)
}
return errors.New("intercepted: " + err.Error())
}
app.Commands = []Command{
Command{
Name: "bar",
},
}
err := app.Run([]string{"foo", "--flag=wrong"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
t.Errorf("Expect an intercepted error, but got \"%v\"", err)
}
}
func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) {
app := NewApp()
app.Flags = []Flag{
IntFlag{Name: "flag"},
}
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
if isSubcommand {
t.Errorf("Expect subcommand")
}
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err)
}
return errors.New("intercepted: " + err.Error())
}
app.Commands = []Command{
Command{
Name: "bar",
},
}
err := app.Run([]string{"foo", "--flag=wrong", "bar"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
t.Errorf("Expect an intercepted error, but got \"%v\"", err)
}
}

@ -30,6 +30,10 @@ type Command struct {
After func(context *Context) error After func(context *Context) error
// The function to call when this command is invoked // The function to call when this command is invoked
Action func(context *Context) Action func(context *Context)
// Execute this function if an usage error occurs. This is useful for displaying customized usage error messages.
// This function is able to manipulate the original error in another.
// If this function is not set the "Incorrect usage" is displayed and the execution is interrupted.
OnUsageError func(context *Context, err error) error
// List of child commands // List of child commands
Subcommands []Command Subcommands []Command
// List of flags to parse // List of flags to parse
@ -110,10 +114,15 @@ func (c Command) Run(ctx *Context) (err error) {
} }
if err != nil { if err != nil {
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.") if c.OnUsageError != nil {
fmt.Fprintln(ctx.App.Writer) err := c.OnUsageError(ctx, err)
ShowCommandHelp(ctx, c.Name) return err
return err } else {
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
return err
}
} }
nerr := normalizeFlags(c.Flags, set) nerr := normalizeFlags(c.Flags, set)

@ -68,3 +68,30 @@ func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
t.Errorf("expected text of error from After method, but got none in \"%v\"", err) t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
} }
} }
func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
app := NewApp()
app.Commands = []Command{
Command{
Name: "bar",
Flags: []Flag{
IntFlag{Name: "flag"},
},
OnUsageError: func(c *Context, err error) error {
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err)
}
return errors.New("intercepted: " + err.Error())
},
},
}
err := app.Run([]string{"foo", "bar", "--flag=wrong"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
t.Errorf("Expect an intercepted error, but got \"%v\"", err)
}
}

Loading…
Cancel
Save