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
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
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' is called.
create' is called. Every command will automatically have the '--help' flag added.
### Example

View file

@ -461,7 +461,7 @@ func TestRootHelp(t *testing.T) {
x := fullSetupTest("--help")
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") {
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")
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") {
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")
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") {
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")
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") {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)

View file

@ -40,9 +40,9 @@ type Command struct {
Short string
// The long message shown in the 'help <this-command>' output.
Long string
// Set of flags specific to this command.
// Full set of flags
flags *flag.FlagSet
// Set of flags children commands will inherit
// Set of flags childrens of this command will inherit
pflags *flag.FlagSet
// Run runs the command.
// The args are the arguments after the command name.
@ -206,12 +206,14 @@ Aliases:
Available Commands: {{range .Commands}}{{if .Runnable}}
{{rpad .Use .UsagePadding }} {{.Short}}{{end}}{{end}}
{{end}}
{{ if .HasFlags}} Available Flags:
{{.Flags.FlagUsages}}{{end}}{{if .HasParent}}{{if and (gt .Commands 0) (gt .Parent.Commands 1) }}
{{ if .HasLocalFlags}}Flags:
{{.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}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{end}}
{{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}}`
}
}
@ -707,7 +709,7 @@ func (c *Command) HasParent() bool {
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 {
if c.flags == nil {
c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
@ -720,7 +722,23 @@ func (c *Command) Flags() *flag.FlagSet {
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 {
if c.pflags == nil {
c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
@ -732,6 +750,29 @@ func (c *Command) PersistentFlags() *flag.FlagSet {
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
func (c *Command) ResetFlags() {
c.flagErrorBuf = new(bytes.Buffer)
@ -742,7 +783,7 @@ func (c *Command) ResetFlags() {
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 {
return c.Flags().HasFlags()
}
@ -752,6 +793,16 @@ func (c *Command) HasPersistentFlags() bool {
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
func (c *Command) Flag(name string) (flag *flag.Flag) {
flag = c.Flags().Lookup(name)
@ -791,6 +842,10 @@ func (c *Command) ParseFlags(args []string) (err error) {
return nil
}
func (c *Command) Parent() *Command {
return c.parent
}
func (c *Command) mergePersistentFlags() {
var rmerge func(x *Command)
@ -809,7 +864,3 @@ func (c *Command) mergePersistentFlags() {
rmerge(c)
}
func (c *Command) Parent() *Command {
return c.parent
}