mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
commit
8e127101ec
2 changed files with 47 additions and 62 deletions
|
@ -768,7 +768,7 @@ func TestRootNoCommandHelp(t *testing.T) {
|
||||||
|
|
||||||
func TestRootUnknownCommand(t *testing.T) {
|
func TestRootUnknownCommand(t *testing.T) {
|
||||||
r := noRRSetupTest("bogus")
|
r := noRRSetupTest("bogus")
|
||||||
s := "Error: unknown command \"bogus\"\nRun 'cobra-test help' for usage.\n"
|
s := "Error: unknown command \"bogus\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n"
|
||||||
|
|
||||||
if r.Output != s {
|
if r.Output != s {
|
||||||
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
|
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
|
||||||
|
|
83
command.go
83
command.go
|
@ -84,7 +84,6 @@ type Command struct {
|
||||||
commandsMaxNameLen int
|
commandsMaxNameLen int
|
||||||
|
|
||||||
flagErrorBuf *bytes.Buffer
|
flagErrorBuf *bytes.Buffer
|
||||||
cmdErrorBuf *bytes.Buffer
|
|
||||||
|
|
||||||
args []string // actual args parsed from flags
|
args []string // actual args parsed from flags
|
||||||
output *io.Writer // nil means stderr; use Out() method instead
|
output *io.Writer // nil means stderr; use Out() method instead
|
||||||
|
@ -274,7 +273,7 @@ Additional help topics:
|
||||||
{{if .HasHelpSubCommands}}{{range .Commands}}{{if and (not .Runnable) (not .Deprecated)}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasRunnableSiblings }}{{range .Parent.Commands}}{{if and (not .Runnable) (not .Deprecated)}}{{if not (eq .Name $cmd.Name) }}
|
{{if .HasHelpSubCommands}}{{range .Commands}}{{if and (not .Runnable) (not .Deprecated)}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasRunnableSiblings }}{{range .Parent.Commands}}{{if and (not .Runnable) (not .Deprecated)}}{{if not (eq .Name $cmd.Name) }}
|
||||||
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{end}}
|
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{end}}
|
||||||
{{end}}{{ if .HasSubCommands }}
|
{{end}}{{ if .HasSubCommands }}
|
||||||
Use "{{.Root.Name}} help [command]" for more information about a command.
|
Use "{{.CommandPath}} [command] --help" for more information about a command.
|
||||||
{{end}}`
|
{{end}}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,29 +380,25 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||||
return nil, nil, fmt.Errorf("Called find() on a nil Command")
|
return nil, nil, fmt.Errorf("Called find() on a nil Command")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no arguments, return the root command. If the root has no
|
|
||||||
// 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, innerArgs []string) (*Command, []string) {
|
innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
|
||||||
if len(innerArgs) > 0 && c.HasSubCommands() {
|
|
||||||
argsWOflags := stripFlags(innerArgs, c)
|
argsWOflags := stripFlags(innerArgs, c)
|
||||||
if len(argsWOflags) > 0 {
|
if len(argsWOflags) == 0 {
|
||||||
|
return c, innerArgs
|
||||||
|
}
|
||||||
|
nextSubCmd := 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() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match
|
||||||
return innerfind(cmd, argsMinusFirstX(innerArgs, argsWOflags[0]))
|
return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
|
||||||
} else if EnablePrefixMatching {
|
}
|
||||||
if strings.HasPrefix(cmd.Name(), argsWOflags[0]) { // prefix match
|
if EnablePrefixMatching {
|
||||||
|
if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match
|
||||||
matches = append(matches, cmd)
|
matches = append(matches, cmd)
|
||||||
}
|
}
|
||||||
for _, x := range cmd.Aliases {
|
for _, x := range cmd.Aliases {
|
||||||
if strings.HasPrefix(x, argsWOflags[0]) {
|
if strings.HasPrefix(x, nextSubCmd) {
|
||||||
matches = append(matches, cmd)
|
matches = append(matches, cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,18 +409,20 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||||
if len(matches) == 1 {
|
if len(matches) == 1 {
|
||||||
return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0]))
|
return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0]))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, innerArgs
|
return c, innerArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
commandFound, a := innerfind(c, args)
|
commandFound, a := innerfind(c, args)
|
||||||
|
|
||||||
// If we matched on the root, but we asked for a subcommand, return an error
|
|
||||||
argsWOflags := stripFlags(a, commandFound)
|
argsWOflags := stripFlags(a, commandFound)
|
||||||
|
|
||||||
|
// no subcommand, always take args
|
||||||
|
if !commandFound.HasSubCommands() {
|
||||||
|
return commandFound, a, nil
|
||||||
|
}
|
||||||
|
// root command with subcommands, do subcommand checking
|
||||||
if commandFound == c && len(argsWOflags) > 0 {
|
if commandFound == c && len(argsWOflags) > 0 {
|
||||||
return nil, a, fmt.Errorf("unknown command %q", argsWOflags[0])
|
return commandFound, a, fmt.Errorf("unknown command %q for %q", argsWOflags[0], commandFound.CommandPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
return commandFound, a, nil
|
return commandFound, a, nil
|
||||||
|
@ -455,29 +452,13 @@ func (c *Command) execute(a []string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.ParseFlags(a)
|
err = c.ParseFlags(a)
|
||||||
if err == flag.ErrHelp {
|
|
||||||
c.Help()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We're writing subcommand usage to root command's error buffer to have it displayed to the user
|
|
||||||
r := c.Root()
|
|
||||||
if r.cmdErrorBuf == nil {
|
|
||||||
r.cmdErrorBuf = new(bytes.Buffer)
|
|
||||||
}
|
|
||||||
// for writing the usage to the buffer we need to switch the output temporarily
|
|
||||||
// since Out() returns root output, you also need to revert that on root
|
|
||||||
out := r.Out()
|
|
||||||
r.SetOutput(r.cmdErrorBuf)
|
|
||||||
c.Usage()
|
|
||||||
r.SetOutput(out)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// If help is called, regardless of other flags, we print that.
|
// If help is called, regardless of other flags, return we want help
|
||||||
// Print help also if c.Run is nil.
|
// Also say we need help if c.Run is nil.
|
||||||
if c.helpFlagVal || !c.Runnable() {
|
if c.helpFlagVal || !c.Runnable() {
|
||||||
c.Help()
|
return flag.ErrHelp
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.preRun()
|
c.preRun()
|
||||||
|
@ -557,18 +538,24 @@ func (c *Command) Execute() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd, flags, err := c.Find(args)
|
cmd, flags, err := c.Find(args)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
err = cmd.execute(flags)
|
// If found parse to a subcommand and then failed, talk about the subcommand
|
||||||
|
if cmd != nil {
|
||||||
|
c = cmd
|
||||||
|
}
|
||||||
|
c.Println("Error:", err.Error())
|
||||||
|
c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = cmd.execute(flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == flag.ErrHelp {
|
if err == flag.ErrHelp {
|
||||||
c.Help()
|
cmd.Help()
|
||||||
|
return nil
|
||||||
} else {
|
|
||||||
c.Println("Error:", err.Error())
|
|
||||||
c.Printf("Run '%v help' for usage.\n", c.Root().Name())
|
|
||||||
}
|
}
|
||||||
|
c.Println(cmd.UsageString())
|
||||||
|
c.Println("Error:", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -597,8 +584,6 @@ func (c *Command) initHelp() {
|
||||||
func (c *Command) ResetCommands() {
|
func (c *Command) ResetCommands() {
|
||||||
c.commands = nil
|
c.commands = nil
|
||||||
c.helpCommand = nil
|
c.helpCommand = nil
|
||||||
c.cmdErrorBuf = new(bytes.Buffer)
|
|
||||||
c.cmdErrorBuf.Reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Commands returns a slice of child commands.
|
//Commands returns a slice of child commands.
|
||||||
|
|
Loading…
Reference in a new issue