2013-07-19 00:29:06 +00:00
|
|
|
package cli
|
|
|
|
|
2013-09-04 19:58:31 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
2013-09-18 16:24:20 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"strings"
|
2013-09-04 19:58:31 +00:00
|
|
|
)
|
|
|
|
|
2013-11-01 14:31:37 +00:00
|
|
|
// Command is a subcommand for a cli.App.
|
2013-07-19 00:29:06 +00:00
|
|
|
type Command struct {
|
2013-11-01 14:31:37 +00:00
|
|
|
// The name of the command
|
|
|
|
Name string
|
|
|
|
// short name of the command. Typically one character
|
|
|
|
ShortName string
|
|
|
|
// A short description of the usage of this command
|
|
|
|
Usage string
|
2014-04-16 16:18:00 +00:00
|
|
|
// A longer explanation of how the command works
|
2013-09-24 01:41:31 +00:00
|
|
|
Description string
|
2014-04-10 17:14:13 +00:00
|
|
|
// The function to call when checking for bash command completions
|
|
|
|
BashComplete func(context *Context)
|
2014-04-16 20:26:28 +00:00
|
|
|
// An action to execute before any sub-subcommands are run, but after the context is ready
|
|
|
|
// If a non-nil error is returned, no sub-subcommands are run
|
|
|
|
Before func(context *Context) error
|
2013-11-01 14:31:37 +00:00
|
|
|
// The function to call when this command is invoked
|
|
|
|
Action func(context *Context)
|
2014-04-16 16:18:00 +00:00
|
|
|
// List of child commands
|
|
|
|
Subcommands []Command
|
2014-04-16 20:26:28 +00:00
|
|
|
// List of flags to parse
|
|
|
|
Flags []Flag
|
2014-04-14 21:44:32 +00:00
|
|
|
// Treat all flags as normal arguments if true
|
|
|
|
SkipFlagParsing bool
|
2014-07-13 13:16:30 +00:00
|
|
|
// Boolean to hide built-in help command
|
|
|
|
HideHelp bool
|
2013-07-19 00:29:06 +00:00
|
|
|
}
|
2013-07-19 02:23:00 +00:00
|
|
|
|
2013-11-01 14:31:37 +00:00
|
|
|
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
2013-11-01 13:45:19 +00:00
|
|
|
func (c Command) Run(ctx *Context) error {
|
2014-04-17 16:48:00 +00:00
|
|
|
|
|
|
|
if len(c.Subcommands) > 0 || c.Before != nil {
|
2014-04-16 16:18:00 +00:00
|
|
|
return c.startApp(ctx)
|
|
|
|
}
|
|
|
|
|
2014-07-13 13:16:30 +00:00
|
|
|
if !c.HideHelp {
|
|
|
|
// append help to flags
|
|
|
|
c.Flags = append(
|
|
|
|
c.Flags,
|
|
|
|
HelpFlag,
|
|
|
|
)
|
|
|
|
}
|
2013-08-14 04:40:39 +00:00
|
|
|
|
2014-04-12 13:32:53 +00:00
|
|
|
if ctx.App.EnableBashCompletion {
|
|
|
|
c.Flags = append(c.Flags, BashCompletionFlag)
|
|
|
|
}
|
|
|
|
|
2013-07-20 15:21:20 +00:00
|
|
|
set := flagSet(c.Name, c.Flags)
|
2013-09-04 19:58:31 +00:00
|
|
|
set.SetOutput(ioutil.Discard)
|
2013-09-18 16:24:20 +00:00
|
|
|
|
|
|
|
firstFlagIndex := -1
|
|
|
|
for index, arg := range ctx.Args() {
|
|
|
|
if strings.HasPrefix(arg, "-") {
|
|
|
|
firstFlagIndex = index
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
2014-04-29 14:21:19 +00:00
|
|
|
if firstFlagIndex > -1 && !c.SkipFlagParsing {
|
2013-11-24 13:40:21 +00:00
|
|
|
args := ctx.Args()
|
|
|
|
regularArgs := args[1:firstFlagIndex]
|
|
|
|
flagArgs := args[firstFlagIndex:]
|
|
|
|
err = set.Parse(append(flagArgs, regularArgs...))
|
2013-09-18 16:24:20 +00:00
|
|
|
} else {
|
2013-11-24 13:40:21 +00:00
|
|
|
err = set.Parse(ctx.Args().Tail())
|
2013-09-18 16:24:20 +00:00
|
|
|
}
|
2013-09-04 19:58:31 +00:00
|
|
|
|
2015-03-02 19:56:29 +00:00
|
|
|
// Define here so it closes over the above variables
|
|
|
|
showErrAndHelp := func(err error) {
|
|
|
|
fmt.Println(err)
|
|
|
|
fmt.Println("")
|
2013-09-04 19:58:31 +00:00
|
|
|
ShowCommandHelp(ctx, c.Name)
|
|
|
|
fmt.Println("")
|
2015-03-02 19:56:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
showErrAndHelp(fmt.Errorf("Incorrect Usage."))
|
2013-11-01 13:45:19 +00:00
|
|
|
return err
|
2013-09-04 19:58:31 +00:00
|
|
|
}
|
2013-08-14 04:40:39 +00:00
|
|
|
|
2013-11-20 08:05:18 +00:00
|
|
|
nerr := normalizeFlags(c.Flags, set)
|
|
|
|
if nerr != nil {
|
2015-03-02 19:56:29 +00:00
|
|
|
showErrAndHelp(nerr)
|
2013-11-20 08:05:18 +00:00
|
|
|
return nerr
|
|
|
|
}
|
2014-12-02 17:44:55 +00:00
|
|
|
|
|
|
|
cerr := checkRequiredFlags(c.Flags, set)
|
|
|
|
if cerr != nil {
|
2015-03-02 19:56:29 +00:00
|
|
|
showErrAndHelp(cerr)
|
2014-12-02 17:44:55 +00:00
|
|
|
return cerr
|
|
|
|
}
|
|
|
|
|
2013-08-14 04:40:39 +00:00
|
|
|
context := NewContext(ctx.App, set, ctx.globalSet)
|
2014-04-10 17:14:13 +00:00
|
|
|
|
|
|
|
if checkCommandCompletions(context, c.Name) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2013-11-01 13:45:19 +00:00
|
|
|
if checkCommandHelp(context, c.Name) {
|
|
|
|
return nil
|
|
|
|
}
|
2014-03-29 19:02:05 +00:00
|
|
|
context.Command = c
|
2013-08-14 04:40:39 +00:00
|
|
|
c.Action(context)
|
2013-11-01 13:45:19 +00:00
|
|
|
return nil
|
2013-07-19 02:23:00 +00:00
|
|
|
}
|
2013-07-19 02:30:18 +00:00
|
|
|
|
2013-11-01 14:31:37 +00:00
|
|
|
// Returns true if Command.Name or Command.ShortName matches given name
|
2013-07-20 15:21:20 +00:00
|
|
|
func (c Command) HasName(name string) bool {
|
|
|
|
return c.Name == name || c.ShortName == name
|
2013-07-19 02:30:18 +00:00
|
|
|
}
|
2014-04-16 16:18:00 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-07-25 17:06:04 +00:00
|
|
|
// set CommandNotFound
|
|
|
|
app.CommandNotFound = ctx.App.CommandNotFound
|
|
|
|
|
2014-04-16 16:18:00 +00:00
|
|
|
// set the flags and commands
|
|
|
|
app.Commands = c.Subcommands
|
|
|
|
app.Flags = c.Flags
|
2014-07-13 13:16:30 +00:00
|
|
|
app.HideHelp = c.HideHelp
|
2014-04-16 16:18:00 +00:00
|
|
|
|
|
|
|
// bash completion
|
|
|
|
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
|
|
|
if c.BashComplete != nil {
|
|
|
|
app.BashComplete = c.BashComplete
|
|
|
|
}
|
|
|
|
|
2014-04-16 20:26:28 +00:00
|
|
|
// set the actions
|
|
|
|
app.Before = c.Before
|
2014-04-16 16:18:00 +00:00
|
|
|
if c.Action != nil {
|
|
|
|
app.Action = c.Action
|
|
|
|
} else {
|
|
|
|
app.Action = helpSubcommand.Action
|
|
|
|
}
|
|
|
|
|
|
|
|
return app.RunAsSubcommand(ctx)
|
|
|
|
}
|