* Added ability to customize usage error messages
This commit is contained in:
parent
f9cc3001e0
commit
7319f042e4
30
app.go
30
app.go
@ -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 {
|
||||||
|
61
app_test.go
61
app_test.go
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
17
command.go
17
command.go
@ -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…
Reference in New Issue
Block a user