github.com/scorpionis/hub@v2.2.1+incompatible/commands/commands.go (about)

     1  package commands
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  
     8  	flag "github.com/github/hub/Godeps/_workspace/src/github.com/ogier/pflag"
     9  	"github.com/github/hub/ui"
    10  )
    11  
    12  var (
    13  	NameRe          = "[\\w.][\\w.-]*"
    14  	OwnerRe         = "[a-zA-Z0-9][a-zA-Z0-9-]*"
    15  	NameWithOwnerRe = fmt.Sprintf("^(?:%s|%s\\/%s)$", NameRe, OwnerRe, NameRe)
    16  
    17  	CmdRunner = NewRunner()
    18  )
    19  
    20  type Command struct {
    21  	Run  func(cmd *Command, args *Args)
    22  	Flag flag.FlagSet
    23  
    24  	Key          string
    25  	Usage        string
    26  	Short        string
    27  	Long         string
    28  	GitExtension bool
    29  
    30  	subCommands map[string]*Command
    31  }
    32  
    33  func (c *Command) Call(args *Args) (err error) {
    34  	runCommand, err := c.lookupSubCommand(args)
    35  	if err != nil {
    36  		ui.Errorln(err)
    37  		return
    38  	}
    39  
    40  	if !c.GitExtension {
    41  		err = runCommand.parseArguments(args)
    42  		if err != nil {
    43  			return
    44  		}
    45  	}
    46  
    47  	runCommand.Run(runCommand, args)
    48  
    49  	return
    50  }
    51  
    52  func (c *Command) parseArguments(args *Args) (err error) {
    53  	c.Flag.SetInterspersed(true)
    54  	c.Flag.Init(c.Name(), flag.ContinueOnError)
    55  	c.Flag.Usage = c.PrintUsage
    56  	if err = c.Flag.Parse(args.Params); err == nil {
    57  		args.Params = c.Flag.Args()
    58  	}
    59  
    60  	return
    61  }
    62  
    63  func (c *Command) Use(subCommand *Command) {
    64  	if c.subCommands == nil {
    65  		c.subCommands = make(map[string]*Command)
    66  	}
    67  	c.subCommands[subCommand.Name()] = subCommand
    68  }
    69  
    70  func (c *Command) PrintUsage() {
    71  	if c.Runnable() {
    72  		ui.Printf("usage: %s\n\n", c.FormattedUsage())
    73  	}
    74  
    75  	ui.Println(strings.Trim(c.Long, "\n"))
    76  }
    77  
    78  func (c *Command) FormattedUsage() string {
    79  	return fmt.Sprintf("git %s", c.Usage)
    80  }
    81  
    82  func (c *Command) subCommandsUsage() string {
    83  	buffer := bytes.NewBufferString("")
    84  
    85  	usage := "usage"
    86  	usage = printUsageBuffer(c, buffer, usage)
    87  	for _, s := range c.subCommands {
    88  		usage = printUsageBuffer(s, buffer, usage)
    89  	}
    90  
    91  	return buffer.String()
    92  }
    93  
    94  func printUsageBuffer(c *Command, b *bytes.Buffer, usage string) string {
    95  	if c.Runnable() {
    96  		b.WriteString(fmt.Sprintf("%s: %s\n", usage, c.FormattedUsage()))
    97  		usage = "   or"
    98  	}
    99  	return usage
   100  }
   101  
   102  func (c *Command) Name() string {
   103  	if c.Key != "" {
   104  		return c.Key
   105  	}
   106  	return strings.Split(c.Usage, " ")[0]
   107  }
   108  
   109  func (c *Command) Runnable() bool {
   110  	return c.Run != nil
   111  }
   112  
   113  func (c *Command) List() bool {
   114  	return c.Short != ""
   115  }
   116  
   117  func (c *Command) lookupSubCommand(args *Args) (runCommand *Command, err error) {
   118  	if len(c.subCommands) > 0 && args.HasSubcommand() {
   119  		subCommandName := args.FirstParam()
   120  		if subCommand, ok := c.subCommands[subCommandName]; ok {
   121  			runCommand = subCommand
   122  			args.Params = args.Params[1:]
   123  		} else {
   124  			err = fmt.Errorf("error: Unknown subcommand: %s\n%s", subCommandName, c.subCommandsUsage())
   125  		}
   126  	} else {
   127  		runCommand = c
   128  	}
   129  
   130  	return
   131  }