Do not parse commands after seeing a non-option non-command arg
Fixes #170.
diff --git a/command_test.go b/command_test.go
index e7e3089..dc04b66 100644
--- a/command_test.go
+++ b/command_test.go
@@ -441,6 +441,20 @@
}
}
+func TestAfterNonCommand(t *testing.T) {
+ var opts = struct {
+ Value bool `short:"v"`
+
+ Cmd1 struct {
+ } `command:"remove"`
+
+ Cmd2 struct {
+ } `command:"add"`
+ }{}
+
+ assertParseFail(t, ErrUnknownCommand, "Unknown command `nocmd'. Please specify one command of: add or remove", &opts, "nocmd", "remove")
+}
+
func TestSubcommandsOptional(t *testing.T) {
var opts = struct {
Value bool `short:"v"`
@@ -467,6 +481,30 @@
}
}
+func TestSubcommandsOptionalAfterNonCommand(t *testing.T) {
+ var opts = struct {
+ Value bool `short:"v"`
+
+ Cmd1 struct {
+ } `command:"remove"`
+
+ Cmd2 struct {
+ } `command:"add"`
+ }{}
+
+ p := NewParser(&opts, None)
+ p.SubcommandsOptional = true
+
+ retargs, err := p.ParseArgs([]string{"nocmd", "remove"})
+
+ if err != nil {
+ t.Fatalf("Unexpected error: %v", err)
+ return
+ }
+
+ assertStringArray(t, retargs, []string{"nocmd", "remove"})
+}
+
func TestCommandAlias(t *testing.T) {
var opts = struct {
Command struct {
diff --git a/parser.go b/parser.go
index 2290941..a52647c 100644
--- a/parser.go
+++ b/parser.go
@@ -620,10 +620,19 @@
return s.addArgs(s.arg)
}
- if cmd := s.lookup.commands[s.arg]; cmd != nil {
- s.command.Active = cmd
- cmd.fillParseState(s)
- } else if (p.Options & PassAfterNonOption) != None {
+ if len(s.command.commands) > 0 && len(s.retargs) == 0 {
+ if cmd := s.lookup.commands[s.arg]; cmd != nil {
+ s.command.Active = cmd
+ cmd.fillParseState(s)
+
+ return nil
+ } else if !s.command.SubcommandsOptional {
+ s.addArgs(s.arg)
+ return newErrorf(ErrUnknownCommand, "Unknown command `%s'", s.arg)
+ }
+ }
+
+ if (p.Options & PassAfterNonOption) != None {
// If PassAfterNonOption is set then all remaining arguments
// are considered positional
if err := s.addArgs(s.arg); err != nil {