urfave-cli/command.go

161 lines
3.8 KiB
Go
Raw Normal View History

package cli
import (
"fmt"
"io/ioutil"
"strings"
)
2013-11-01 14:31:37 +00:00
// Command is a subcommand for a cli.App.
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
// 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)
// 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
2014-11-18 22:44:21 +00:00
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
2014-11-18 22:44:21 +00:00
After 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)
// List of child commands
Subcommands []Command
// 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 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
func (c Command) Run(ctx *Context) error {
2014-11-18 22:44:21 +00:00
if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil {
return c.startApp(ctx)
}
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
2014-07-13 13:16:30 +00:00
// append help to flags
c.Flags = append(
c.Flags,
HelpFlag,
)
}
2013-08-14 04:40:39 +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)
set.SetOutput(ioutil.Discard)
firstFlagIndex := -1
terminatorIndex := -1
for index, arg := range ctx.Args() {
if arg == "--" {
terminatorIndex = index
break
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
firstFlagIndex = index
}
}
var err error
if firstFlagIndex > -1 && !c.SkipFlagParsing {
2013-11-24 13:40:21 +00:00
args := ctx.Args()
regularArgs := make([]string, len(args[1:firstFlagIndex]))
copy(regularArgs, args[1:firstFlagIndex])
var flagArgs []string
if terminatorIndex > -1 {
flagArgs = args[firstFlagIndex:terminatorIndex]
regularArgs = append(regularArgs, args[terminatorIndex:]...)
} else {
flagArgs = args[firstFlagIndex:]
}
2013-11-24 13:40:21 +00:00
err = set.Parse(append(flagArgs, regularArgs...))
} else {
2013-11-24 13:40:21 +00:00
err = set.Parse(ctx.Args().Tail())
}
if err != nil {
fmt.Fprint(ctx.App.Writer, "Incorrect Usage.\n\n")
ShowCommandHelp(ctx, c.Name)
fmt.Fprintln(ctx.App.Writer)
return err
}
2013-08-14 04:40:39 +00:00
2013-11-20 08:05:18 +00:00
nerr := normalizeFlags(c.Flags, set)
if nerr != nil {
fmt.Fprintln(ctx.App.Writer, nerr)
fmt.Fprintln(ctx.App.Writer)
2013-11-20 08:05:18 +00:00
ShowCommandHelp(ctx, c.Name)
fmt.Fprintln(ctx.App.Writer)
2013-11-20 08:05:18 +00:00
return nerr
}
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
}
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)
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
}
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 CommandNotFound
app.CommandNotFound = ctx.App.CommandNotFound
// 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
// bash completion
app.EnableBashCompletion = ctx.App.EnableBashCompletion
if c.BashComplete != nil {
app.BashComplete = c.BashComplete
}
// set the actions
app.Before = c.Before
2014-11-18 22:44:21 +00:00
app.After = c.After
if c.Action != nil {
app.Action = c.Action
} else {
app.Action = helpSubcommand.Action
}
return app.RunAsSubcommand(ctx)
}