Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Verify that the subcommand found is a complete command #40

Merged
merged 1 commit into from
Aug 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"os"
"regexp"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -405,16 +406,24 @@ func (c *CLI) processArgs() {
}

// If we didn't find a subcommand yet and this is the first non-flag
// argument, then this is our subcommand. j
// argument, then this is our subcommand.
if c.subcommand == "" && arg != "" && arg[0] != '-' {
c.subcommand = arg
if c.commandNested {
// Nested CLI, the subcommand is actually the entire
// arg list up to a flag that is still a valid subcommand.
k, _, ok := c.commandTree.LongestPrefix(strings.Join(c.Args[i:], " "))
searchKey := strings.Join(c.Args[i:], " ")
k, _, ok := c.commandTree.LongestPrefix(searchKey)
if ok {
c.subcommand = k
i += strings.Count(k, " ")
// k could be a prefix that doesn't contain the full
// command such as "foo" instead of "foobar", so we
// need to verify that we have an entire key. To do that,
// we look for an ending in a space or an end of string.
reVerify := regexp.MustCompile(regexp.QuoteMeta(k) + `( |$)`)
if reVerify.MatchString(searchKey) {
c.subcommand = k
i += strings.Count(k, " ")
}
}
}

Expand Down
31 changes: 31 additions & 0 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,37 @@ func TestCLIRun_blank(t *testing.T) {
}
}

func TestCLIRun_prefix(t *testing.T) {
buf := new(bytes.Buffer)
command := new(MockCommand)
cli := &CLI{
Args: []string{"foobar"},
Commands: map[string]CommandFactory{
"foo": func() (Command, error) {
return command, nil
},

"foo bar": func() (Command, error) {
return command, nil
},
},
HelpWriter: buf,
}

exitCode, err := cli.Run()
if err != nil {
t.Fatalf("err: %s", err)
}

if exitCode != 1 {
t.Fatalf("bad: %d", exitCode)
}

if command.RunCalled {
t.Fatalf("run should not be called")
}
}

func TestCLIRun_default(t *testing.T) {
commandBar := new(MockCommand)
commandBar.RunResult = 42
Expand Down