diff --git a/cobra_test.go b/cobra_test.go index 96fffb48..fb4a7c4d 100644 --- a/cobra_test.go +++ b/cobra_test.go @@ -47,6 +47,12 @@ var cmdRootNoRun = &Command{ Long: "The root description for help", } +var cmdRootSameName = &Command{ + Use: "print", + Short: "Root with the same name as a subcommand", + Long: "The root description for help", +} + var cmdRootWithRun = &Command{ Use: "cobra-test", Short: "The root can run it's own function", @@ -65,6 +71,7 @@ func flagInit() { cmdPrint.ResetFlags() cmdTimes.ResetFlags() cmdRootNoRun.ResetFlags() + cmdRootSameName.ResetFlags() cmdRootWithRun.ResetFlags() cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone") cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo") @@ -81,6 +88,9 @@ func commandInit() { cmdEcho.ResetCommands() cmdPrint.ResetCommands() cmdTimes.ResetCommands() + cmdRootNoRun.ResetCommands() + cmdRootSameName.ResetCommands() + cmdRootWithRun.ResetCommands() } func initialize() *Command { @@ -91,6 +101,14 @@ func initialize() *Command { return c } +func initializeWithSameName() *Command { + tt, tp, te = nil, nil, nil + var c = cmdRootSameName + flagInit() + commandInit() + return c +} + func initializeWithRootCmd() *Command { cmdRootWithRun.ResetCommands() tt, tp, te, rootcalled = nil, nil, nil, false @@ -136,6 +154,58 @@ func TestChildCommand(t *testing.T) { } } +func TestChildCommandPrefix(t *testing.T) { + c := initialize() + cmdEcho.AddCommand(cmdTimes) + c.AddCommand(cmdPrint, cmdEcho) + c.SetArgs(strings.Split("ech tim one two", " ")) + c.Execute() + + if te != nil || tp != nil { + t.Error("Wrong command called") + } + if tt == nil { + t.Error("Wrong command called") + } + if strings.Join(tt, " ") != "one two" { + t.Error("Command didn't parse correctly") + } +} + +func TestChildSameName(t *testing.T) { + c := initializeWithSameName() + c.AddCommand(cmdPrint, cmdEcho) + c.SetArgs(strings.Split("print one two", " ")) + c.Execute() + + if te != nil || tt != nil { + t.Error("Wrong command called") + } + if tp == nil { + t.Error("Wrong command called") + } + if strings.Join(tp, " ") != "one two" { + t.Error("Command didn't parse correctly") + } +} + +func TestChildSameNamePrefix(t *testing.T) { + c := initializeWithSameName() + c.AddCommand(cmdPrint, cmdEcho) + c.SetArgs(strings.Split("pr one two", " ")) + c.Execute() + + if te != nil || tt != nil { + t.Error("Wrong command called") + } + if tp == nil { + t.Error("Wrong command called") + } + if strings.Join(tp, " ") != "one two" { + t.Error("Command didn't parse correctly") + } +} + func TestFlagLong(t *testing.T) { c := initialize() c.AddCommand(cmdPrint, cmdEcho, cmdTimes) diff --git a/command.go b/command.go index 73d009f7..663681a8 100644 --- a/command.go +++ b/command.go @@ -239,11 +239,19 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) { innerfind = func(c *Command, args []string) (*Command, []string) { if len(args) > 0 && c.HasSubCommands() { + matches := make([]*Command, 0) for _, cmd := range c.commands { - if cmd.Name() == args[0] { + if cmd.Name() == args[0] { // exact name match return innerfind(cmd, args[1:]) + } else if strings.HasPrefix(cmd.Name(), args[0]) { // prefix match + matches = append(matches, cmd) } } + + // only accept a single prefix match - multiple matches would be ambiguous + if len(matches) == 1 { + return innerfind(matches[0], args[1:]) + } } return c, args @@ -252,7 +260,7 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) { commandFound, a := innerfind(c, arrs) // if commander returned and not appropriately matched return nil & error - if commandFound.Name() == c.Name() && commandFound.Name() != arrs[0] { + if commandFound.Name() == c.Name() && !strings.HasPrefix(commandFound.Name(), arrs[0]) { return nil, a, fmt.Errorf("unknown command %q\nRun 'help' for usage.\n", a[0]) }