diff --git a/README.md b/README.md
index 81b9505..fa90ad5 100644
--- a/README.md
+++ b/README.md
@@ -293,6 +293,8 @@ type CLI struct {
}
```
+If a sub-command is tagged with `default:"1"` it will be selected if there are no further arguments.
+
## Branching positional arguments
@@ -419,6 +421,7 @@ Tag | Description
`type:"X"` | Specify [named types](#custom-named-types) to use.
`placeholder:"X"` | Placeholder text.
`default:"X"` | Default value.
+`default:"1"` | On a command, make it the default.
`short:"X"` | Short name, if flag.
`required` | If present, flag/arg is required.
`optional` | If present, flag/arg is optional.
diff --git a/context.go b/context.go
index 9baca0e..86e6f5b 100644
--- a/context.go
+++ b/context.go
@@ -397,6 +397,24 @@ func (c *Context) trace(node *Node) (err error) { // nolint: gocyclo
return fmt.Errorf("unexpected token %s", token)
}
}
+
+ // End of the line, check for a default command.
+ var defaultNode *Path
+ for _, child := range node.Children {
+ if child.Type == CommandNode && child.Tag.Default != "" {
+ if defaultNode != nil {
+ return fmt.Errorf("can't have more than one default command under %s", node.Summary())
+ }
+ defaultNode = &Path{
+ Parent: child,
+ Command: child,
+ Flags: child.Flags,
+ }
+ }
+ }
+ if defaultNode != nil {
+ c.Path = append(c.Path, defaultNode)
+ }
return nil
}
@@ -617,6 +635,7 @@ func checkMissingChildren(node *Node) error {
missing = append(missing, strconv.Quote(strings.Join(missingArgs, " ")))
}
+ haveDefault := 0
for _, child := range node.Children {
if child.Hidden {
continue
@@ -627,10 +646,19 @@ func checkMissingChildren(node *Node) error {
}
missing = append(missing, strconv.Quote(child.Summary()))
} else {
+ if child.Tag.Default != "" {
+ if len(child.Children) > 0 {
+ return fmt.Errorf("default command %s must not have subcommands or arguments", child.Summary())
+ }
+ haveDefault++
+ }
missing = append(missing, strconv.Quote(child.Name))
}
}
- if len(missing) == 0 {
+ if haveDefault > 1 {
+ return fmt.Errorf("more than one default command found under %s", node.Summary())
+ }
+ if len(missing) == 0 || haveDefault > 0 {
return nil
}
diff --git a/kong_test.go b/kong_test.go
index 75a7fcd..b55093a 100644
--- a/kong_test.go
+++ b/kong_test.go
@@ -815,3 +815,38 @@ func TestIssue40EnumAcrossCommands(t *testing.T) {
_, err = p.Parse([]string{"three", "c"})
require.NoError(t, err)
}
+
+func TestEnumArg(t *testing.T) {
+ var cli struct {
+ Nested struct {
+ One string `arg:"" enum:"a,b,c"`
+ Two string `arg:""`
+ } `cmd:""`
+ }
+ p := mustNew(t, &cli)
+ _, err := p.Parse([]string{"nested", "a", "b"})
+ require.NoError(t, err)
+ require.Equal(t, "a", cli.Nested.One)
+ require.Equal(t, "b", cli.Nested.Two)
+}
+
+func TestDefaultCommand(t *testing.T) {
+ var cli struct {
+ One struct{} `cmd:"" default:"1"`
+ Two struct{} `cmd:""`
+ }
+ p := mustNew(t, &cli)
+ ctx, err := p.Parse([]string{})
+ require.NoError(t, err)
+ require.Equal(t, "one", ctx.Command())
+}
+
+func TestMultipleDefaultCommands(t *testing.T) {
+ var cli struct {
+ One struct{} `cmd:"" default:"1"`
+ Two struct{} `cmd:"" default:"1"`
+ }
+ p := mustNew(t, &cli)
+ _, err := p.Parse([]string{})
+ require.EqualError(t, err, "can't have more than one default command under ")
+}