github.com/jduhamel/gcli@v0.2.4-0.20151019142748-0d5307cd7e21/skeleton/resource/tmpl/go_cmd/main.go.tmpl (about) 1 package main 2 3 import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "io" 8 "log" 9 "os" 10 "strings" 11 "text/template" 12 ) 13 14 // A Command is an implementation of a {{ .Name }} command 15 type Command struct { 16 // Run runs the command. 17 // The args are the arguments after the command name. 18 Run func(args []string) int 19 20 // UsageLine is the one-line usage message. 21 // The first word in the line is taken to be the command name. 22 UsageLine string 23 24 // Short is the short description shown in the '{{ .Name }} help' output. 25 Short string 26 27 // Long is the long message shown in the '{{ .Name }} help <this-command>' output. 28 Long string 29 30 // Flag is a set of flags specific to this command. 31 Flag flag.FlagSet 32 } 33 34 // Name returns the command's name: the first word in the usage line. 35 func (c *Command) Name() string { 36 name := c.UsageLine 37 i := strings.Index(name, " ") 38 if i >= 0 { 39 name = name[:i] 40 } 41 return name 42 } 43 44 func (c *Command) Usage() { 45 fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine) 46 fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long)) 47 os.Exit(2) 48 } 49 50 // Commands lists the available commands and help topics. 51 // The order here is the order in which they are printed by '{{ .Name }} help'. 52 var commands = []*Command{ 53 {{ range .Commands }}cmd{{ title .FunctionName }}, 54 {{ end }} 55 } 56 57 func main() { 58 59 flag.Usage = usage 60 flag.Parse() 61 log.SetFlags(0) 62 63 args := flag.Args() 64 if len(args) < 1 { 65 usage() 66 } 67 68 if args[0] == "help" { 69 help(args[1:]) 70 return 71 } 72 73 for _, cmd := range commands { 74 if cmd.Name() == args[0] { 75 cmd.Flag.Usage = func() { cmd.Usage() } 76 77 cmd.Flag.Parse(args[1:]) 78 args = cmd.Flag.Args() 79 80 os.Exit(cmd.Run(args)) 81 } 82 } 83 84 fmt.Fprintf(os.Stderr, "{{ .Name }}: unknown subcommand %q\nRun ' {{ .Name }} help' for usage.\n", args[0]) 85 os.Exit(2) 86 } 87 88 var usageTemplate = `{{ .Name }} is a tool for {{ .Description }} 89 90 Usage: 91 92 {{ .Name }} command [arguments] 93 94 The commands are: 95 {{"{{range .}}"}} 96 {{"{{.Name | printf "}}"%-11s"{{"}} {{.Short}}{{end}}"}} 97 98 Use "{{ .Name }} help [command]" for more information about a command. 99 100 ` 101 102 var helpTemplate = `usage: {{ .Name }} {{"{{.UsageLine}}"}} 103 104 {{"{{.Long | trim}}"}} 105 ` 106 107 // tmpl executes the given template text on data, writing the result to w. 108 func tmpl(w io.Writer, text string, data interface{}) { 109 t := template.New("top") 110 t.Funcs(template.FuncMap{"trim": strings.TrimSpace}) 111 template.Must(t.Parse(text)) 112 if err := t.Execute(w, data); err != nil { 113 panic(err) 114 } 115 } 116 117 func printUsage(w io.Writer) { 118 bw := bufio.NewWriter(w) 119 tmpl(bw, usageTemplate, commands) 120 bw.Flush() 121 } 122 123 func usage() { 124 printUsage(os.Stderr) 125 os.Exit(2) 126 } 127 128 // help implements the 'help' command. 129 func help(args []string) { 130 if len(args) == 0 { 131 printUsage(os.Stdout) 132 // not exit 2: succeeded at '{{ .Name }} help'. 133 return 134 } 135 if len(args) != 1 { 136 fmt.Fprintf(os.Stderr, "usage: {{ .Name }} help command\n\nToo many arguments given.\n") 137 os.Exit(2) // failed at '{{ .Name }} help' 138 } 139 140 arg := args[0] 141 142 for _, cmd := range commands { 143 if cmd.Name() == arg { 144 tmpl(os.Stdout, helpTemplate, cmd) 145 // not exit 2: succeeded at '{{ .Name }} help cmd'. 146 return 147 } 148 } 149 150 fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run '{{ .Name }} help'.\n", arg) 151 os.Exit(2) // failed at '{{ .Name }} help cmd' 152 }