mirror of
https://github.com/spf13/cobra
synced 2024-11-24 22:57:12 +00:00
Fix root command without subcommands but with arguments
This commit is contained in:
parent
bba56042cf
commit
62abfcbd80
2 changed files with 48 additions and 17 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
var _ = fmt.Println
|
var _ = fmt.Println
|
||||||
var _ = os.Stderr
|
var _ = os.Stderr
|
||||||
|
|
||||||
var tp, te, tt, t1 []string
|
var tp, te, tt, t1, tr []string
|
||||||
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
|
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
|
||||||
var flagb1, flagb2, flagb3, flagbr, flagbp bool
|
var flagb1, flagb2, flagb3, flagbr, flagbp bool
|
||||||
var flags1, flags2a, flags2b, flags3 string
|
var flags1, flags2a, flags2b, flags3 string
|
||||||
|
@ -99,6 +100,7 @@ var cmdRootWithRun = &Command{
|
||||||
Short: "The root can run it's own function",
|
Short: "The root can run it's own function",
|
||||||
Long: "The root description for help",
|
Long: "The root description for help",
|
||||||
Run: func(cmd *Command, args []string) {
|
Run: func(cmd *Command, args []string) {
|
||||||
|
tr = args
|
||||||
rootcalled = true
|
rootcalled = true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -181,7 +183,7 @@ func initializeWithSameName() *Command {
|
||||||
|
|
||||||
func initializeWithRootCmd() *Command {
|
func initializeWithRootCmd() *Command {
|
||||||
cmdRootWithRun.ResetCommands()
|
cmdRootWithRun.ResetCommands()
|
||||||
tt, tp, te, rootcalled = nil, nil, nil, false
|
tt, tp, te, tr, rootcalled = nil, nil, nil, nil, false
|
||||||
flagInit()
|
flagInit()
|
||||||
cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot")
|
cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot")
|
||||||
cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot")
|
cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot")
|
||||||
|
@ -494,7 +496,7 @@ func TestTrailingCommandFlags(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidSubCommandFlags(t *testing.T) {
|
func TestInvalidSubcommandFlags(t *testing.T) {
|
||||||
cmd := initializeWithRootCmd()
|
cmd := initializeWithRootCmd()
|
||||||
cmd.AddCommand(cmdTimes)
|
cmd.AddCommand(cmdTimes)
|
||||||
|
|
||||||
|
@ -508,7 +510,7 @@ func TestInvalidSubCommandFlags(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubCommandArgEvaluation(t *testing.T) {
|
func TestSubcommandArgEvaluation(t *testing.T) {
|
||||||
cmd := initializeWithRootCmd()
|
cmd := initializeWithRootCmd()
|
||||||
|
|
||||||
first := &Command{
|
first := &Command{
|
||||||
|
@ -819,6 +821,31 @@ func TestRemoveCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommandWithoutSubcommands(t *testing.T) {
|
||||||
|
c := initializeWithRootCmd()
|
||||||
|
|
||||||
|
x := simpleTester(c, "")
|
||||||
|
if x.Error != nil {
|
||||||
|
t.Errorf("Calling command without subcommands should not have error: %v", x.Error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCommandWithoutSubcommandsWithArg(t *testing.T) {
|
||||||
|
c := initializeWithRootCmd()
|
||||||
|
expectedArgs := []string{"arg"}
|
||||||
|
|
||||||
|
x := simpleTester(c, "arg")
|
||||||
|
if x.Error != nil {
|
||||||
|
t.Errorf("Calling command without subcommands but with arg should not have error: %v", x.Error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(expectedArgs, tr) {
|
||||||
|
t.Errorf("Calling command without subcommands but with arg has wrong args: expected: %v, actual: %v", expectedArgs, tr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestReplaceCommandWithRemove(t *testing.T) {
|
func TestReplaceCommandWithRemove(t *testing.T) {
|
||||||
versionUsed = 0
|
versionUsed = 0
|
||||||
c := initializeWithRootCmd()
|
c := initializeWithRootCmd()
|
||||||
|
|
30
command.go
30
command.go
|
@ -18,13 +18,14 @@ package cobra
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/inconshreveable/mousetrap"
|
|
||||||
flag "github.com/spf13/pflag"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/inconshreveable/mousetrap"
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Command is just that, a command for your application.
|
// Command is just that, a command for your application.
|
||||||
|
@ -360,25 +361,28 @@ func argsMinusFirstX(args []string, x string) []string {
|
||||||
|
|
||||||
// find the target command given the args and command tree
|
// find the target command given the args and command tree
|
||||||
// Meant to be run on the highest node. Only searches down.
|
// Meant to be run on the highest node. Only searches down.
|
||||||
func (c *Command) Find(arrs []string) (*Command, []string, error) {
|
func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, nil, fmt.Errorf("Called find() on a nil Command")
|
return nil, nil, fmt.Errorf("Called find() on a nil Command")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(arrs) == 0 {
|
// If there are no arguments, return the root command. If the root has no
|
||||||
return c.Root(), arrs, nil
|
// subcommands, args reflects arguments that should actually be passed to
|
||||||
|
// the root command, so also return the root command.
|
||||||
|
if len(args) == 0 || !c.Root().HasSubCommands() {
|
||||||
|
return c.Root(), args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var innerfind func(*Command, []string) (*Command, []string)
|
var innerfind func(*Command, []string) (*Command, []string)
|
||||||
|
|
||||||
innerfind = func(c *Command, args []string) (*Command, []string) {
|
innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
|
||||||
if len(args) > 0 && c.HasSubCommands() {
|
if len(innerArgs) > 0 && c.HasSubCommands() {
|
||||||
argsWOflags := stripFlags(args, c)
|
argsWOflags := stripFlags(innerArgs, c)
|
||||||
if len(argsWOflags) > 0 {
|
if len(argsWOflags) > 0 {
|
||||||
matches := make([]*Command, 0)
|
matches := make([]*Command, 0)
|
||||||
for _, cmd := range c.commands {
|
for _, cmd := range c.commands {
|
||||||
if cmd.Name() == argsWOflags[0] || cmd.HasAlias(argsWOflags[0]) { // exact name or alias match
|
if cmd.Name() == argsWOflags[0] || cmd.HasAlias(argsWOflags[0]) { // exact name or alias match
|
||||||
return innerfind(cmd, argsMinusFirstX(args, argsWOflags[0]))
|
return innerfind(cmd, argsMinusFirstX(innerArgs, argsWOflags[0]))
|
||||||
} else if EnablePrefixMatching {
|
} else if EnablePrefixMatching {
|
||||||
if strings.HasPrefix(cmd.Name(), argsWOflags[0]) { // prefix match
|
if strings.HasPrefix(cmd.Name(), argsWOflags[0]) { // prefix match
|
||||||
matches = append(matches, cmd)
|
matches = append(matches, cmd)
|
||||||
|
@ -393,18 +397,18 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) {
|
||||||
|
|
||||||
// only accept a single prefix match - multiple matches would be ambiguous
|
// only accept a single prefix match - multiple matches would be ambiguous
|
||||||
if len(matches) == 1 {
|
if len(matches) == 1 {
|
||||||
return innerfind(matches[0], argsMinusFirstX(args, argsWOflags[0]))
|
return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, args
|
return c, innerArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
commandFound, a := innerfind(c, arrs)
|
commandFound, a := innerfind(c, args)
|
||||||
|
|
||||||
// If we matched on the root, but we asked for a subcommand, return an error
|
// If we matched on the root, but we asked for a subcommand, return an error
|
||||||
if commandFound.Name() == c.Name() && len(stripFlags(arrs, c)) > 0 && commandFound.Name() != arrs[0] {
|
if commandFound.Name() == c.Name() && len(stripFlags(args, c)) > 0 && commandFound.Name() != args[0] {
|
||||||
return nil, a, fmt.Errorf("unknown command %q", a[0])
|
return nil, a, fmt.Errorf("unknown command %q", a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue