Merge github.com:spf13/cobra

This commit is contained in:
Alexander Thaller 2015-02-17 20:40:08 +01:00
commit 50142bdfe4
3 changed files with 69 additions and 18 deletions

View file

@ -216,11 +216,11 @@ For a more complete example of a larger application, please checkout [Hugo](http
## The Help Command ## The Help Command
Cobra automatically adds a help command to your application. Cobra automatically adds a help command to your application when you have subcommands.
This will be called when a user runs 'app help'. Additionally help will also This will be called when a user runs 'app help'. Additionally help will also
support all other commands as input. Say for instance you have a command called support all other commands as input. Say for instance you have a command called
'create' without any additional configuration cobra will work when 'app help 'create' without any additional configuration cobra will work when 'app help
create' is called. create' is called. Every command will automatically have the '--help' flag added.
### Example ### Example

View file

@ -461,7 +461,7 @@ func TestRootHelp(t *testing.T) {
x := fullSetupTest("--help") x := fullSetupTest("--help")
checkResultContains(t, x, "Available Commands:") checkResultContains(t, x, "Available Commands:")
checkResultContains(t, x, "for more information about that command") checkResultContains(t, x, "for more information about a command")
if strings.Contains(x.Output, "unknown flag: --help") { if strings.Contains(x.Output, "unknown flag: --help") {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
@ -470,7 +470,7 @@ func TestRootHelp(t *testing.T) {
x = fullSetupTest("echo --help") x = fullSetupTest("echo --help")
checkResultContains(t, x, "Available Commands:") checkResultContains(t, x, "Available Commands:")
checkResultContains(t, x, "for more information about that command") checkResultContains(t, x, "for more information about a command")
if strings.Contains(x.Output, "unknown flag: --help") { if strings.Contains(x.Output, "unknown flag: --help") {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
@ -482,7 +482,7 @@ func TestRootNoCommandHelp(t *testing.T) {
x := rootOnlySetupTest("--help") x := rootOnlySetupTest("--help")
checkResultOmits(t, x, "Available Commands:") checkResultOmits(t, x, "Available Commands:")
checkResultOmits(t, x, "for more information about that command") checkResultOmits(t, x, "for more information about a command")
if strings.Contains(x.Output, "unknown flag: --help") { if strings.Contains(x.Output, "unknown flag: --help") {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
@ -491,7 +491,7 @@ func TestRootNoCommandHelp(t *testing.T) {
x = rootOnlySetupTest("echo --help") x = rootOnlySetupTest("echo --help")
checkResultOmits(t, x, "Available Commands:") checkResultOmits(t, x, "Available Commands:")
checkResultOmits(t, x, "for more information about that command") checkResultOmits(t, x, "for more information about a command")
if strings.Contains(x.Output, "unknown flag: --help") { if strings.Contains(x.Output, "unknown flag: --help") {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)

View file

@ -40,9 +40,9 @@ type Command struct {
Short string Short string
// The long message shown in the 'help <this-command>' output. // The long message shown in the 'help <this-command>' output.
Long string Long string
// Set of flags specific to this command. // Full set of flags
flags *flag.FlagSet flags *flag.FlagSet
// Set of flags children commands will inherit // Set of flags childrens of this command will inherit
pflags *flag.FlagSet pflags *flag.FlagSet
// Run runs the command. // Run runs the command.
// The args are the arguments after the command name. // The args are the arguments after the command name.
@ -206,12 +206,14 @@ Aliases:
Available Commands: {{range .Commands}}{{if .Runnable}} Available Commands: {{range .Commands}}{{if .Runnable}}
{{rpad .Use .UsagePadding }} {{.Short}}{{end}}{{end}} {{rpad .Use .UsagePadding }} {{.Short}}{{end}}{{end}}
{{end}} {{end}}
{{ if .HasFlags}} Available Flags: {{ if .HasLocalFlags}}Flags:
{{.Flags.FlagUsages}}{{end}}{{if .HasParent}}{{if and (gt .Commands 0) (gt .Parent.Commands 1) }} {{.LocalFlags.FlagUsages}}{{end}}
{{ if .HasAnyPersistentFlags}}Global Flags:
{{.AllPersistentFlags.FlagUsages}}{{end}}{{if .HasParent}}{{if and (gt .Commands 0) (gt .Parent.Commands 1) }}
Additional help topics: {{if gt .Commands 0 }}{{range .Commands}}{{if not .Runnable}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if gt .Parent.Commands 1 }}{{range .Parent.Commands}}{{if .Runnable}}{{if not (eq .Name $cmd.Name) }}{{end}} Additional help topics: {{if gt .Commands 0 }}{{range .Commands}}{{if not .Runnable}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if gt .Parent.Commands 1 }}{{range .Parent.Commands}}{{if .Runnable}}{{if not (eq .Name $cmd.Name) }}{{end}}
{{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 that command. Use "{{.Root.Name}} help [command]" for more information about a command.
{{end}}` {{end}}`
} }
} }
@ -707,7 +709,7 @@ func (c *Command) HasParent() bool {
return c.parent != nil return c.parent != nil
} }
// Get the Commands FlagSet // Get the complete FlagSet that applies to this command (local and persistent declared here and by all parents)
func (c *Command) Flags() *flag.FlagSet { func (c *Command) Flags() *flag.FlagSet {
if c.flags == nil { if c.flags == nil {
c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
@ -720,7 +722,23 @@ func (c *Command) Flags() *flag.FlagSet {
return c.flags return c.flags
} }
// Get the Commands Persistent FlagSet // Get the local FlagSet specifically set in the current command
func (c *Command) LocalFlags() *flag.FlagSet {
c.mergePersistentFlags()
local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
allPersistent := c.AllPersistentFlags()
c.Flags().VisitAll(func(f *flag.Flag) {
if allPersistent.Lookup(f.Name) == nil {
local.AddFlag(f)
}
})
return local
}
// Get the Persistent FlagSet specifically set in the current command
func (c *Command) PersistentFlags() *flag.FlagSet { func (c *Command) PersistentFlags() *flag.FlagSet {
if c.pflags == nil { if c.pflags == nil {
c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
@ -732,6 +750,29 @@ func (c *Command) PersistentFlags() *flag.FlagSet {
return c.pflags return c.pflags
} }
// Get the Persistent FlagSet traversing the Command hierarchy
func (c *Command) AllPersistentFlags() *flag.FlagSet {
allPersistent := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
var visit func(x *Command)
visit = func(x *Command) {
if x.HasPersistentFlags() {
x.PersistentFlags().VisitAll(func(f *flag.Flag) {
if allPersistent.Lookup(f.Name) == nil {
allPersistent.AddFlag(f)
}
})
}
if x.HasParent() {
visit(x.parent)
}
}
visit(c)
return allPersistent
}
// For use in testing // For use in testing
func (c *Command) ResetFlags() { func (c *Command) ResetFlags() {
c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf = new(bytes.Buffer)
@ -742,7 +783,7 @@ func (c *Command) ResetFlags() {
c.pflags.SetOutput(c.flagErrorBuf) c.pflags.SetOutput(c.flagErrorBuf)
} }
// Does the command contain flags (local not persistent) // Does the command contain any flags (local plus persistent from the entire structure)
func (c *Command) HasFlags() bool { func (c *Command) HasFlags() bool {
return c.Flags().HasFlags() return c.Flags().HasFlags()
} }
@ -752,6 +793,16 @@ func (c *Command) HasPersistentFlags() bool {
return c.PersistentFlags().HasFlags() return c.PersistentFlags().HasFlags()
} }
// Does the command hierarchy contain persistent flags
func (c *Command) HasAnyPersistentFlags() bool {
return c.AllPersistentFlags().HasFlags()
}
// Does the command has flags specifically declared locally
func (c *Command) HasLocalFlags() bool {
return c.LocalFlags().HasFlags()
}
// Climbs up the command tree looking for matching flag // Climbs up the command tree looking for matching flag
func (c *Command) Flag(name string) (flag *flag.Flag) { func (c *Command) Flag(name string) (flag *flag.Flag) {
flag = c.Flags().Lookup(name) flag = c.Flags().Lookup(name)
@ -791,6 +842,10 @@ func (c *Command) ParseFlags(args []string) (err error) {
return nil return nil
} }
func (c *Command) Parent() *Command {
return c.parent
}
func (c *Command) mergePersistentFlags() { func (c *Command) mergePersistentFlags() {
var rmerge func(x *Command) var rmerge func(x *Command)
@ -809,7 +864,3 @@ func (c *Command) mergePersistentFlags() {
rmerge(c) rmerge(c)
} }
func (c *Command) Parent() *Command {
return c.parent
}