From a062611ecf33c3cbb6f757b7a09516835e5122cf Mon Sep 17 00:00:00 2001 From: hasheddan Date: Sun, 4 Oct 2020 19:27:12 -0500 Subject: [PATCH] Do not run parent node on missing child err with usageOnMissing option Refactors usageOnMissing option to not run parent commands after printing usage when a child node is missing. Signed-off-by: hasheddan --- context.go | 16 +++++----------- error.go | 31 +++++++++++++++++++++++++++++++ kong.go | 5 ++++- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/context.go b/context.go index b4d1ee2..244c672 100644 --- a/context.go +++ b/context.go @@ -187,9 +187,6 @@ func (c *Context) Validate() error { // nolint: gocyclo } if err := checkMissingChildren(node); err != nil { - if c.Kong.usageOnMissing { - return c.PrintUsage(false) - } return err } if err := checkMissingPositionals(positionals, node.Positional); err != nil { @@ -628,10 +625,13 @@ func (c *Context) Run(binds ...interface{}) (err error) { node := c.Selected() if node == nil { if c.Kong.usageOnMissing { - return nil + return c.PrintUsage(false) } return fmt.Errorf("no command selected") } + if c.Kong.usageOnMissing && isMissingChildError(c.Error) { + return c.PrintUsage(false) + } return c.RunNode(node, binds...) } @@ -700,13 +700,7 @@ func checkMissingChildren(node *Node) error { return nil } - if len(missing) > 5 { - missing = append(missing[:5], "...") - } - if len(missing) == 1 { - return fmt.Errorf("expected %s", missing[0]) - } - return fmt.Errorf("expected one of %s", strings.Join(missing, ", ")) + return newMissingChildError(missing) } // If we're missing any positionals and they're required, return an error. diff --git a/error.go b/error.go index 30b8858..36f512b 100644 --- a/error.go +++ b/error.go @@ -1,5 +1,10 @@ package kong +import ( + "fmt" + "strings" +) + // ParseError is the error type returned by Kong.Parse(). // // It contains the parse Context that triggered the error. @@ -10,3 +15,29 @@ type ParseError struct { // Cause returns the original cause of the error. func (p *ParseError) Cause() error { return p.error } + +type missingChildError struct { + missing []string +} + +func (m *missingChildError) Error() string { + if len(m.missing) > 5 { + m.missing = append(m.missing[:5], "...") + } + if len(m.missing) == 1 { + return fmt.Sprintf("expected %s", m.missing[0]) + } + return fmt.Sprintf("expected one of %s", strings.Join(m.missing, ", ")) +} + +func newMissingChildError(missing []string) *missingChildError { + return &missingChildError{missing} +} + +func isMissingChildError(err error) bool { + if err == nil { + return false + } + _, ok := err.(*missingChildError) + return ok +} diff --git a/kong.go b/kong.go index c16b723..d46915e 100644 --- a/kong.go +++ b/kong.go @@ -219,7 +219,10 @@ func (k *Kong) Parse(args []string) (ctx *Context, err error) { return nil, &ParseError{error: err, Context: ctx} } if err = ctx.Validate(); err != nil { - return nil, &ParseError{error: err, Context: ctx} + if !k.usageOnError || !isMissingChildError(err) { + return nil, &ParseError{error: err, Context: ctx} + } + ctx.Error = err } if err = k.applyHook(ctx, "AfterApply"); err != nil { return nil, &ParseError{error: err, Context: ctx}