github.com/pengwynn/gh@v1.0.1-0.20140118055701-14327ca3942e/commands/commands.go (about)

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