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 }