options: Add kong.ShortUsageOnError() option
Add kong.ShortUsageOnError() option similar to kong.UsageOnError().
Add tests for UsageOnError and ShortUsageOnError.
Remove the HelpOption summary reset at the beginning of DefaultHelpPrinter:
func DefaultHelpPrinter(options HelpOptions, ctx *Context) error {
- if ctx.Empty() {
- options.Summary = false
- }
⚠️ I'm not really sure what the implications of this are, tests still
seem to pass, but maybe this has unintended side effects.
This commit is contained in:
@@ -87,6 +87,21 @@ func DefaultHelpValueFormatter(value *Value) string {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultShortHelpPrinter is the default HelpPrinter for short help on error.
|
||||
func DefaultShortHelpPrinter(options HelpOptions, ctx *Context) error {
|
||||
w := newHelpWriter(ctx, options)
|
||||
cmd := ctx.Selected()
|
||||
app := ctx.Model
|
||||
if cmd == nil {
|
||||
w.Printf("Usage: %s%s", app.Name, app.Summary())
|
||||
w.Printf(`Run "%s --help" for more information.`, app.Name)
|
||||
} else {
|
||||
w.Printf("Usage: %s %s", app.Name, cmd.Summary())
|
||||
w.Printf(`Run "%s --help" for more information.`, cmd.FullPath())
|
||||
}
|
||||
return w.Write(ctx.Stdout)
|
||||
}
|
||||
|
||||
// DefaultHelpPrinter is the default HelpPrinter.
|
||||
func DefaultHelpPrinter(options HelpOptions, ctx *Context) error {
|
||||
if ctx.Empty() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package kong_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -512,3 +513,80 @@ Group 2
|
||||
require.Equal(t, expected, w.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUsageOnError(t *testing.T) {
|
||||
var cli struct {
|
||||
Flag string `help:"A required flag." required`
|
||||
}
|
||||
w := &strings.Builder{}
|
||||
p := mustNew(t, &cli,
|
||||
kong.Writers(w, w),
|
||||
kong.Description("Some description."),
|
||||
kong.Exit(func(int) {}),
|
||||
kong.UsageOnError(),
|
||||
)
|
||||
_, err := p.Parse([]string{})
|
||||
p.FatalIfErrorf(err)
|
||||
|
||||
expected := `Usage: test --flag=STRING
|
||||
|
||||
Some description.
|
||||
|
||||
Flags:
|
||||
-h, --help Show context-sensitive help.
|
||||
--flag=STRING A required flag.
|
||||
|
||||
test: error: missing flags: --flag=STRING
|
||||
`
|
||||
require.Equal(t, expected, w.String())
|
||||
}
|
||||
|
||||
func TestShortUsageOnError(t *testing.T) {
|
||||
var cli struct {
|
||||
Flag string `help:"A required flag." required`
|
||||
}
|
||||
w := &strings.Builder{}
|
||||
p := mustNew(t, &cli,
|
||||
kong.Writers(w, w),
|
||||
kong.Description("Some description."),
|
||||
kong.Exit(func(int) {}),
|
||||
kong.ShortUsageOnError(),
|
||||
)
|
||||
_, err := p.Parse([]string{})
|
||||
require.Error(t, err)
|
||||
p.FatalIfErrorf(err)
|
||||
|
||||
expected := `Usage: test --flag=STRING
|
||||
Run "test --help" for more information.
|
||||
|
||||
test: error: missing flags: --flag=STRING
|
||||
`
|
||||
require.Equal(t, expected, w.String())
|
||||
}
|
||||
|
||||
func TestCustomShortUsageOnError(t *testing.T) {
|
||||
var cli struct {
|
||||
Flag string `help:"A required flag." required`
|
||||
}
|
||||
w := &strings.Builder{}
|
||||
shortHelp := func(_ kong.HelpOptions, ctx *kong.Context) error {
|
||||
fmt.Fprintln(ctx.Stdout, "🤷 wish I could help")
|
||||
return nil
|
||||
}
|
||||
p := mustNew(t, &cli,
|
||||
kong.Writers(w, w),
|
||||
kong.Description("Some description."),
|
||||
kong.Exit(func(int) {}),
|
||||
kong.ShortHelp(shortHelp),
|
||||
kong.ShortUsageOnError(),
|
||||
)
|
||||
_, err := p.Parse([]string{})
|
||||
require.Error(t, err)
|
||||
p.FatalIfErrorf(err)
|
||||
|
||||
expected := `🤷 wish I could help
|
||||
|
||||
test: error: missing flags: --flag=STRING
|
||||
`
|
||||
require.Equal(t, expected, w.String())
|
||||
}
|
||||
|
||||
@@ -31,6 +31,13 @@ func Must(ast interface{}, options ...Option) *Kong {
|
||||
return k
|
||||
}
|
||||
|
||||
type usageOnError int
|
||||
|
||||
const (
|
||||
shortUsage usageOnError = iota + 1
|
||||
fullUsage
|
||||
)
|
||||
|
||||
// Kong is the main parser type.
|
||||
type Kong struct {
|
||||
// Grammar model.
|
||||
@@ -48,8 +55,9 @@ type Kong struct {
|
||||
registry *Registry
|
||||
|
||||
noDefaultHelp bool
|
||||
usageOnError bool
|
||||
usageOnError usageOnError
|
||||
help HelpPrinter
|
||||
shortHelp HelpPrinter
|
||||
helpFormatter HelpValueFormatter
|
||||
helpOptions HelpOptions
|
||||
helpFlag *Flag
|
||||
@@ -86,6 +94,10 @@ func New(grammar interface{}, options ...Option) (*Kong, error) {
|
||||
k.help = DefaultHelpPrinter
|
||||
}
|
||||
|
||||
if k.shortHelp == nil {
|
||||
k.shortHelp = DefaultShortHelpPrinter
|
||||
}
|
||||
|
||||
model, err := build(k, grammar)
|
||||
if err != nil {
|
||||
return k, err
|
||||
@@ -331,10 +343,15 @@ func (k *Kong) FatalIfErrorf(err error, args ...interface{}) {
|
||||
msg = fmt.Sprintf(args[0].(string), args[1:]...) + ": " + err.Error()
|
||||
}
|
||||
// Maybe display usage information.
|
||||
if err, ok := err.(*ParseError); ok && k.usageOnError {
|
||||
options := k.helpOptions
|
||||
_ = k.help(options, err.Context)
|
||||
fmt.Fprintln(k.Stdout)
|
||||
if err, ok := err.(*ParseError); ok {
|
||||
switch k.usageOnError {
|
||||
case fullUsage:
|
||||
_ = k.help(k.helpOptions, err.Context)
|
||||
fmt.Fprintln(k.Stdout)
|
||||
case shortUsage:
|
||||
_ = k.shortHelp(k.helpOptions, err.Context)
|
||||
fmt.Fprintln(k.Stdout)
|
||||
}
|
||||
}
|
||||
k.Fatalf("%s", msg)
|
||||
}
|
||||
|
||||
+22
-1
@@ -192,6 +192,17 @@ func Help(help HelpPrinter) Option {
|
||||
})
|
||||
}
|
||||
|
||||
// ShortHelp configures the short usage message.
|
||||
//
|
||||
// It should be used together with kong.ShortUsageOnError() to display a
|
||||
// custom short usage message on errors.
|
||||
func ShortHelp(shortHelp HelpPrinter) Option {
|
||||
return OptionFunc(func(k *Kong) error {
|
||||
k.shortHelp = shortHelp
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// HelpFormatter configures how the help text is formatted.
|
||||
func HelpFormatter(helpFormatter HelpValueFormatter) Option {
|
||||
return OptionFunc(func(k *Kong) error {
|
||||
@@ -251,7 +262,17 @@ func ExplicitGroups(groups []Group) Option {
|
||||
// UsageOnError configures Kong to display context-sensitive usage if FatalIfErrorf is called with an error.
|
||||
func UsageOnError() Option {
|
||||
return OptionFunc(func(k *Kong) error {
|
||||
k.usageOnError = true
|
||||
k.usageOnError = fullUsage
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ShortUsageOnError configures Kong to display context-sensitive short
|
||||
// usage if FatalIfErrorf is called with an error. The default short
|
||||
// usage message can be overridden with kong.ShortHelp(...).
|
||||
func ShortUsageOnError() Option {
|
||||
return OptionFunc(func(k *Kong) error {
|
||||
k.usageOnError = shortUsage
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user