123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- package cli
- import (
- "fmt"
- "io/ioutil"
- "sort"
- "strings"
- )
- type Command struct {
-
- Name string
-
- ShortName string
-
- Aliases []string
-
- Usage string
-
- UsageText string
-
- Description string
-
- ArgsUsage string
-
- Category string
-
- BashComplete BashCompleteFunc
-
-
- Before BeforeFunc
-
-
- After AfterFunc
-
- Action interface{}
-
-
-
- OnUsageError OnUsageErrorFunc
-
- Subcommands Commands
-
- Flags []Flag
-
- SkipFlagParsing bool
-
-
-
-
- SkipArgReorder bool
-
- HideHelp bool
-
- Hidden bool
-
- HelpName string
- commandNamePath []string
- }
- func (c Command) FullName() string {
- if c.commandNamePath == nil {
- return c.Name
- }
- return strings.Join(c.commandNamePath, " ")
- }
- type Commands []Command
- func (c Command) Run(ctx *Context) (err error) {
- if len(c.Subcommands) > 0 {
- return c.startApp(ctx)
- }
- if !c.HideHelp && (HelpFlag != BoolFlag{}) {
-
- c.Flags = append(
- c.Flags,
- HelpFlag,
- )
- }
- set, err := flagSet(c.Name, c.Flags)
- if err != nil {
- return err
- }
- set.SetOutput(ioutil.Discard)
- if c.SkipFlagParsing {
- err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
- } else if !c.SkipArgReorder {
- firstFlagIndex := -1
- terminatorIndex := -1
- for index, arg := range ctx.Args() {
- if arg == "--" {
- terminatorIndex = index
- break
- } else if arg == "-" {
-
- continue
- } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
- firstFlagIndex = index
- }
- }
- if firstFlagIndex > -1 {
- 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:]
- }
- err = set.Parse(append(flagArgs, regularArgs...))
- } else {
- err = set.Parse(ctx.Args().Tail())
- }
- } else {
- err = set.Parse(ctx.Args().Tail())
- }
- nerr := normalizeFlags(c.Flags, set)
- if nerr != nil {
- fmt.Fprintln(ctx.App.Writer, nerr)
- fmt.Fprintln(ctx.App.Writer)
- ShowCommandHelp(ctx, c.Name)
- return nerr
- }
- context := NewContext(ctx.App, set, ctx)
- if checkCommandCompletions(context, c.Name) {
- return nil
- }
- if err != nil {
- if c.OnUsageError != nil {
- err := c.OnUsageError(ctx, err, false)
- HandleExitCoder(err)
- return err
- }
- fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error())
- fmt.Fprintln(ctx.App.Writer)
- ShowCommandHelp(ctx, c.Name)
- return err
- }
- if checkCommandHelp(context, c.Name) {
- return nil
- }
- if c.After != nil {
- defer func() {
- afterErr := c.After(context)
- if afterErr != nil {
- HandleExitCoder(err)
- if err != nil {
- err = NewMultiError(err, afterErr)
- } else {
- err = afterErr
- }
- }
- }()
- }
- if c.Before != nil {
- err = c.Before(context)
- if err != nil {
- fmt.Fprintln(ctx.App.Writer, err)
- fmt.Fprintln(ctx.App.Writer)
- ShowCommandHelp(ctx, c.Name)
- HandleExitCoder(err)
- return err
- }
- }
- if c.Action == nil {
- c.Action = helpSubcommand.Action
- }
- context.Command = c
- err = HandleAction(c.Action, context)
- if err != nil {
- HandleExitCoder(err)
- }
- return err
- }
- func (c Command) Names() []string {
- names := []string{c.Name}
- if c.ShortName != "" {
- names = append(names, c.ShortName)
- }
- return append(names, c.Aliases...)
- }
- func (c Command) HasName(name string) bool {
- for _, n := range c.Names() {
- if n == name {
- return true
- }
- }
- return false
- }
- func (c Command) startApp(ctx *Context) error {
- app := NewApp()
- app.Metadata = ctx.App.Metadata
-
- app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
- if c.HelpName == "" {
- app.HelpName = c.HelpName
- } else {
- app.HelpName = app.Name
- }
- if c.Description != "" {
- app.Usage = c.Description
- } else {
- app.Usage = c.Usage
- }
-
- app.CommandNotFound = ctx.App.CommandNotFound
-
- app.Commands = c.Subcommands
- app.Flags = c.Flags
- app.HideHelp = c.HideHelp
- app.Version = ctx.App.Version
- app.HideVersion = ctx.App.HideVersion
- app.Compiled = ctx.App.Compiled
- app.Author = ctx.App.Author
- app.Email = ctx.App.Email
- app.Writer = ctx.App.Writer
- app.categories = CommandCategories{}
- for _, command := range c.Subcommands {
- app.categories = app.categories.AddCommand(command.Category, command)
- }
- sort.Sort(app.categories)
-
- app.EnableBashCompletion = ctx.App.EnableBashCompletion
- if c.BashComplete != nil {
- app.BashComplete = c.BashComplete
- }
-
- app.Before = c.Before
- app.After = c.After
- if c.Action != nil {
- app.Action = c.Action
- } else {
- app.Action = helpSubcommand.Action
- }
- for index, cc := range app.Commands {
- app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
- }
- return app.RunAsSubcommand(ctx)
- }
- func (c Command) VisibleFlags() []Flag {
- return visibleFlags(c.Flags)
- }
|