Correctly check for required positionals.

This commit is contained in:
Alec Thomas
2018-06-20 22:36:33 +10:00
parent 653531d6bc
commit 4edc701d63
2 changed files with 39 additions and 26 deletions
+4
View File
@@ -1,6 +1,8 @@
package main package main
import ( import (
"fmt"
"github.com/alecthomas/kong" "github.com/alecthomas/kong"
) )
@@ -24,6 +26,8 @@ func main() {
cmd := kong.Parse(&cli, kong.Description("A shell-like example app."), kong.HelpOptions(kong.CompactHelp())) cmd := kong.Parse(&cli, kong.Description("A shell-like example app."), kong.HelpOptions(kong.CompactHelp()))
switch cmd { switch cmd {
case "rm": case "rm":
fmt.Println(cli.Rm.Paths, cli.Rm.Force)
case "ls": case "ls":
} }
} }
+35 -26
View File
@@ -25,6 +25,21 @@ type Path struct {
Resolved bool Resolved bool
} }
// Node returns the Node associated with this Path, or nil if Path is a non-Node.
func (p *Path) Node() *Node {
switch {
case p.App != nil:
return &p.App.Node
case p.Argument != nil:
return p.Argument
case p.Command != nil:
return p.Command
}
return nil
}
// Context contains the current parse context. // Context contains the current parse context.
type Context struct { type Context struct {
App *Kong App *Kong
@@ -90,36 +105,30 @@ func (c *Context) Validate() error {
} }
} }
// Check the terminal node. // Check the terminal node.
path := c.Path[len(c.Path)-1] node := c.Selected()
switch { if node == nil {
case path.App != nil: node = &c.App.Model.Node
if err := checkMissingChildren(&path.App.Node); err != nil { }
return err
}
if err := checkMissingPositionals(0, path.App.Positional); err != nil {
return err
}
case path.Command != nil: // Find deepest positional argument so we can check if all required positionals have been provided.
if err := checkMissingChildren(path.Command); err != nil { positionals := 0
return err for _, path := range c.Path {
} if path.Positional != nil {
if err := checkMissingPositionals(0, path.Parent.Positional); err != nil { positionals = path.Positional.Position + 1
return err
} }
}
case path.Argument != nil: if err := checkMissingChildren(node); err != nil {
value := path.Argument.Argument return err
}
if err := checkMissingPositionals(positionals, node.Positional); err != nil {
return err
}
if node.Type == ArgumentNode {
value := node.Argument
if value.Required && !value.Set { if value.Required && !value.Set {
return fmt.Errorf("%s is required", path.Argument.Summary()) return fmt.Errorf("%s is required", node.Summary())
}
if err := checkMissingChildren(path.Argument); err != nil {
return err
}
case path.Positional != nil:
if err := checkMissingPositionals(path.Positional.Position+1, path.Parent.Positional); err != nil {
return err
} }
} }
return nil return nil