More consistent implementation of recursive subcommands
This commit is contained in:
parent
640826c88f
commit
13f0c8c0f6
56
app.go
56
app.go
@ -129,6 +129,62 @@ func (a *App) Run(arguments []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
|
||||||
|
func (a *App) RunAsSubcommand(c *Context) error {
|
||||||
|
// append help to commands
|
||||||
|
if a.Command(helpCommand.Name) == nil {
|
||||||
|
a.Commands = append(a.Commands, helpCommand)
|
||||||
|
}
|
||||||
|
|
||||||
|
// append help flags
|
||||||
|
if a.EnableBashCompletion {
|
||||||
|
a.appendFlag(BashCompletionFlag)
|
||||||
|
}
|
||||||
|
a.appendFlag(BoolFlag{"help, h", "show help"})
|
||||||
|
|
||||||
|
// parse flags
|
||||||
|
set := flagSet(a.Name, a.Flags)
|
||||||
|
set.SetOutput(ioutil.Discard)
|
||||||
|
err := set.Parse(c.Args().Tail())
|
||||||
|
nerr := normalizeFlags(a.Flags, set)
|
||||||
|
context := NewContext(a, set, set)
|
||||||
|
|
||||||
|
if nerr != nil {
|
||||||
|
fmt.Println(nerr)
|
||||||
|
ShowSubcommandHelp(context)
|
||||||
|
fmt.Println("")
|
||||||
|
return nerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Incorrect Usage.\n\n")
|
||||||
|
ShowSubcommandHelp(context)
|
||||||
|
fmt.Println("")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkCompletions(context) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkSubcommandHelp(context) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args := context.Args()
|
||||||
|
if args.Present() {
|
||||||
|
name := args.First()
|
||||||
|
c := a.Command(name)
|
||||||
|
if c != nil {
|
||||||
|
return c.Run(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run default Action
|
||||||
|
a.Action(context)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the named command on App. Returns nil if the command does not exist
|
// Returns the named command on App. Returns nil if the command does not exist
|
||||||
func (a *App) Command(name string) *Command {
|
func (a *App) Command(name string) *Command {
|
||||||
for _, c := range a.Commands {
|
for _, c := range a.Commands {
|
||||||
|
39
command.go
39
command.go
@ -14,7 +14,7 @@ type Command struct {
|
|||||||
ShortName string
|
ShortName string
|
||||||
// A short description of the usage of this command
|
// A short description of the usage of this command
|
||||||
Usage string
|
Usage string
|
||||||
// A longer explaination of how the command works
|
// A longer explanation of how the command works
|
||||||
Description string
|
Description string
|
||||||
// The function to call when checking for bash command completions
|
// The function to call when checking for bash command completions
|
||||||
BashComplete func(context *Context)
|
BashComplete func(context *Context)
|
||||||
@ -22,10 +22,16 @@ type Command struct {
|
|||||||
Action func(context *Context)
|
Action func(context *Context)
|
||||||
// List of flags to parse
|
// List of flags to parse
|
||||||
Flags []Flag
|
Flags []Flag
|
||||||
|
// List of child commands
|
||||||
|
Subcommands []Command
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||||
func (c Command) Run(ctx *Context) error {
|
func (c Command) Run(ctx *Context) error {
|
||||||
|
if len(c.Subcommands) > 0 {
|
||||||
|
return c.startApp(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// append help to flags
|
// append help to flags
|
||||||
c.Flags = append(
|
c.Flags = append(
|
||||||
c.Flags,
|
c.Flags,
|
||||||
@ -89,3 +95,34 @@ func (c Command) Run(ctx *Context) error {
|
|||||||
func (c Command) HasName(name string) bool {
|
func (c Command) HasName(name string) bool {
|
||||||
return c.Name == name || c.ShortName == name
|
return c.Name == name || c.ShortName == name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Command) startApp(ctx *Context) error {
|
||||||
|
app := NewApp()
|
||||||
|
|
||||||
|
// set the name and usage
|
||||||
|
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
||||||
|
if c.Description != "" {
|
||||||
|
app.Usage = c.Description
|
||||||
|
} else {
|
||||||
|
app.Usage = c.Usage
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the flags and commands
|
||||||
|
app.Commands = c.Subcommands
|
||||||
|
app.Flags = c.Flags
|
||||||
|
|
||||||
|
// bash completion
|
||||||
|
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
||||||
|
if c.BashComplete != nil {
|
||||||
|
app.BashComplete = c.BashComplete
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the action
|
||||||
|
if c.Action != nil {
|
||||||
|
app.Action = c.Action
|
||||||
|
} else {
|
||||||
|
app.Action = helpSubcommand.Action
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.RunAsSubcommand(ctx)
|
||||||
|
}
|
||||||
|
46
help.go
46
help.go
@ -44,6 +44,24 @@ OPTIONS:
|
|||||||
{{end}}
|
{{end}}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// The text template for the subcommand help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
var SubcommandHelpTemplate = `NAME:
|
||||||
|
{{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{.Name}} [global options] command [command options] [arguments...]
|
||||||
|
|
||||||
|
COMMANDS:
|
||||||
|
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
{{range .Flags}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
`
|
||||||
|
|
||||||
var helpCommand = Command{
|
var helpCommand = Command{
|
||||||
Name: "help",
|
Name: "help",
|
||||||
ShortName: "h",
|
ShortName: "h",
|
||||||
@ -58,6 +76,20 @@ var helpCommand = Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var helpSubcommand = Command{
|
||||||
|
Name: "help",
|
||||||
|
ShortName: "h",
|
||||||
|
Usage: "Shows a list of commands or help for one command",
|
||||||
|
Action: func(c *Context) {
|
||||||
|
args := c.Args()
|
||||||
|
if args.Present() {
|
||||||
|
ShowCommandHelp(c, args.First())
|
||||||
|
} else {
|
||||||
|
ShowSubcommandHelp(c)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Prints help for the App
|
// Prints help for the App
|
||||||
var HelpPrinter = printHelp
|
var HelpPrinter = printHelp
|
||||||
|
|
||||||
@ -87,6 +119,11 @@ func ShowCommandHelp(c *Context, command string) {
|
|||||||
fmt.Printf("No help topic for '%v'\n", command)
|
fmt.Printf("No help topic for '%v'\n", command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prints help for the given subcommand
|
||||||
|
func ShowSubcommandHelp(c *Context) {
|
||||||
|
HelpPrinter(SubcommandHelpTemplate, c.App)
|
||||||
|
}
|
||||||
|
|
||||||
// Prints the version number of the App
|
// Prints the version number of the App
|
||||||
func ShowVersion(c *Context) {
|
func ShowVersion(c *Context) {
|
||||||
fmt.Printf("%v version %v\n", c.App.Name, c.App.Version)
|
fmt.Printf("%v version %v\n", c.App.Name, c.App.Version)
|
||||||
@ -145,6 +182,15 @@ func checkCommandHelp(c *Context, name string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkSubcommandHelp(c *Context) bool {
|
||||||
|
if c.GlobalBool("h") || c.GlobalBool("help") {
|
||||||
|
ShowSubcommandHelp(c)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func checkCompletions(c *Context) bool {
|
func checkCompletions(c *Context) bool {
|
||||||
if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
|
if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
|
||||||
ShowCompletions(c)
|
ShowCompletions(c)
|
||||||
|
Loading…
Reference in New Issue
Block a user