mirror of
https://github.com/spf13/cobra
synced 2024-11-16 18:57:08 +00:00
Require commands to explicitly state they take arbitrary arguments
The code is riddled with inconsistencies between the root command and subcommands. One of those is that the root command cannot take arbitrary arguments and will complain about invalid subcommands. But subcommands will always take arbitrary arguments and will never complain about invalid sub-sub-commands. I make arbitrary arguments explicitly listed. You now need to set cmd.TakesArgs = true if you need to be able to accept arguments tha aren't flags. This is a pretty major change.
This commit is contained in:
parent
0ea881ce45
commit
5452222cb4
2 changed files with 37 additions and 14 deletions
|
@ -26,6 +26,7 @@ var cmdPrint = &Command{
|
||||||
Use: "print [string to print]",
|
Use: "print [string to print]",
|
||||||
Short: "Print anything to the screen",
|
Short: "Print anything to the screen",
|
||||||
Long: `an absolutely utterly useless command for testing.`,
|
Long: `an absolutely utterly useless command for testing.`,
|
||||||
|
TakesArgs: true,
|
||||||
Run: func(cmd *Command, args []string) {
|
Run: func(cmd *Command, args []string) {
|
||||||
tp = args
|
tp = args
|
||||||
},
|
},
|
||||||
|
@ -36,6 +37,7 @@ var cmdEcho = &Command{
|
||||||
Aliases: []string{"say"},
|
Aliases: []string{"say"},
|
||||||
Short: "Echo anything to the screen",
|
Short: "Echo anything to the screen",
|
||||||
Long: `an utterly useless command for testing.`,
|
Long: `an utterly useless command for testing.`,
|
||||||
|
TakesArgs: true,
|
||||||
Run: func(cmd *Command, args []string) {
|
Run: func(cmd *Command, args []string) {
|
||||||
te = args
|
te = args
|
||||||
},
|
},
|
||||||
|
@ -45,11 +47,20 @@ var cmdTimes = &Command{
|
||||||
Use: "times [# times] [string to echo]",
|
Use: "times [# times] [string to echo]",
|
||||||
Short: "Echo anything to the screen more times",
|
Short: "Echo anything to the screen more times",
|
||||||
Long: `a slightly useless command for testing.`,
|
Long: `a slightly useless command for testing.`,
|
||||||
|
TakesArgs: true,
|
||||||
Run: func(cmd *Command, args []string) {
|
Run: func(cmd *Command, args []string) {
|
||||||
tt = args
|
tt = args
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmdNoArgs = &Command{
|
||||||
|
Use: "noargs [because they don't work!!]",
|
||||||
|
Short: "Runnable, but won't take non-flag args",
|
||||||
|
Long: `something in long form, just because.`,
|
||||||
|
Run: func(cmd *Command, args []string) {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var cmdRootNoRun = &Command{
|
var cmdRootNoRun = &Command{
|
||||||
Use: "cobra-test",
|
Use: "cobra-test",
|
||||||
Short: "The root can run it's own function",
|
Short: "The root can run it's own function",
|
||||||
|
@ -93,6 +104,7 @@ func flagInit() {
|
||||||
cmdEcho.ResetFlags()
|
cmdEcho.ResetFlags()
|
||||||
cmdPrint.ResetFlags()
|
cmdPrint.ResetFlags()
|
||||||
cmdTimes.ResetFlags()
|
cmdTimes.ResetFlags()
|
||||||
|
cmdNoArgs.ResetFlags()
|
||||||
cmdRootNoRun.ResetFlags()
|
cmdRootNoRun.ResetFlags()
|
||||||
cmdRootSameName.ResetFlags()
|
cmdRootSameName.ResetFlags()
|
||||||
cmdRootWithRun.ResetFlags()
|
cmdRootWithRun.ResetFlags()
|
||||||
|
@ -187,7 +199,7 @@ func fullTester(c *Command, input string) resulter {
|
||||||
// Testing flag with invalid input
|
// Testing flag with invalid input
|
||||||
c.SetOutput(buf)
|
c.SetOutput(buf)
|
||||||
cmdEcho.AddCommand(cmdTimes)
|
cmdEcho.AddCommand(cmdTimes)
|
||||||
c.AddCommand(cmdPrint, cmdEcho)
|
c.AddCommand(cmdPrint, cmdEcho, cmdNoArgs)
|
||||||
c.SetArgs(strings.Split(input, " "))
|
c.SetArgs(strings.Split(input, " "))
|
||||||
|
|
||||||
err := c.Execute()
|
err := c.Execute()
|
||||||
|
@ -557,6 +569,12 @@ func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInvalidSubcommandWhenArgsDisallowed(t *testing.T) {
|
||||||
|
x := fullSetupTest("noargs invalid-sub")
|
||||||
|
|
||||||
|
checkResultContains(t, x, "Error: unknown command \"invalid-sub\"\n")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRootFlags(t *testing.T) {
|
func TestRootFlags(t *testing.T) {
|
||||||
fullSetupTest("-i 17 -b")
|
fullSetupTest("-i 17 -b")
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,10 @@ type Command struct {
|
||||||
Long string
|
Long string
|
||||||
// Examples of how to use the command
|
// Examples of how to use the command
|
||||||
Example string
|
Example string
|
||||||
|
// Accepts arguments that are not defined in flags. This makes subcommand checking and
|
||||||
|
// error reporting less strict as we can cannot tell if `command [arg]` is an incorrect
|
||||||
|
// subcommand or just an argument this command will process.
|
||||||
|
TakesArgs bool
|
||||||
// Full set of flags
|
// Full set of flags
|
||||||
flags *flag.FlagSet
|
flags *flag.FlagSet
|
||||||
// Set of flags childrens of this command will inherit
|
// Set of flags childrens of this command will inherit
|
||||||
|
@ -377,8 +381,8 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) {
|
||||||
|
|
||||||
commandFound, a := innerfind(c, arrs)
|
commandFound, a := innerfind(c, arrs)
|
||||||
|
|
||||||
// If we matched on the root, but we asked for a subcommand, return an error
|
// Reject if there are args left and the command doesn't take args
|
||||||
if commandFound.Name() == c.Name() && len(stripFlags(arrs, c)) > 0 && commandFound.Name() != arrs[0] {
|
if commandFound.TakesArgs == false && len(stripFlags(a, commandFound)) > 0 {
|
||||||
return nil, a, fmt.Errorf("unknown command %q", a[0])
|
return nil, a, fmt.Errorf("unknown command %q", a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,6 +521,7 @@ func (c *Command) initHelp() {
|
||||||
Short: "Help about any command",
|
Short: "Help about any command",
|
||||||
Long: `Help provides help for any command in the application.
|
Long: `Help provides help for any command in the application.
|
||||||
Simply type ` + c.Name() + ` help [path to command] for full details.`,
|
Simply type ` + c.Name() + ` help [path to command] for full details.`,
|
||||||
|
TakesArgs: true,
|
||||||
Run: c.HelpFunc(),
|
Run: c.HelpFunc(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue