github.com/trevoraustin/hub@v2.2.0-preview1.0.20141105230840-96d8bfc654cc+incompatible/commands/commands.go (about)

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