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 }