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 }