commands/cli: Use template for helptext generation
Matt Bell committed
Nov 11, 2014 at 21:57 UTC
4970d8b5a3f61f4055f3bca0065487e053212a0e
2 files changed
+89
-49
cmd/ipfs2/main.go
+4
-10
@@ -107,11 +107,9 @@ func createRequest(args []string) (cmds.Request, *cmds.Command, error) {
107
}
108
109
// generate the help text for the command the user was trying to call (or root)
110
- helpText, htErr := cmdsCli.HelpText("ipfs", root, path)
110
+ htErr := cmdsCli.LongHelp("ipfs", root, path, os.Stdout)
111
if htErr != nil {
112
fmt.Println(htErr)
113
- } else {
114
- fmt.Println(helpText)
113
}
114
return nil, nil, err
115
}
@@ -150,12 +148,10 @@ func handleHelpOption(req cmds.Request, root *cmds.Command) (helpTextDisplayed b
148
if !help {
149
return false, nil
150
}
153
- helpText, err := cmdsCli.HelpText("ipfs", root, req.Path())
151
+ err = cmdsCli.LongHelp("ipfs", root, req.Path(), os.Stdout)
152
if err != nil {
153
return false, err
154
}
157
- fmt.Println(helpText)
158
-
155
return true, nil
156
}
157
@@ -214,11 +210,9 @@ func outputResponse(res cmds.Response, root *cmds.Command) error {
210
211
// if this is a client error, we try to display help text
212
if res.Error().Code == cmds.ErrClient {
217
- helpText, err := cmdsCli.HelpText("ipfs", root, res.Request().Path())
213
+ err := cmdsCli.LongHelp("ipfs", root, res.Request().Path(), os.Stdout)
214
if err != nil {
219
- fmt.Println(err.Error())
220
- } else {
221
- fmt.Println(helpText)
215
+ fmt.Println(err)
216
}
217
}
218
commands/cli/helptext.go
+85
-39
@@ -2,7 +2,9 @@ package cli
2
3
import (
4
"fmt"
5
+ "io"
6
"strings"
7
+ "text/template"
8
9
cmds "github.com/jbenet/go-ipfs/commands"
10
)
@@ -15,60 +17,104 @@ const (
17
optionType = "(%v)"
18
19
whitespace = "\r\n\t "
20
+
21
+ indentStr = " "
22
)
23
20
-// HelpText returns a formatted CLI helptext string, generated for the given command
21
-func HelpText(rootName string, root *cmds.Command, path []string) (string, error) {
22
- cmd, err := root.Get(path)
24
+type helpFields struct {
25
+ Indent string
26
+ Path string
27
+ ArgUsage string
28
+ Tagline string
29
+ Arguments string
30
+ Options string
31
+ Subcommands string
32
+ Description string
33
+}
34
+
35
+const usageFormat = "{{.Path}}{{if .ArgUsage}} {{.ArgUsage}}{{end}} - {{.Tagline}}"
36
+
37
+const longHelpFormat = `
38
+{{.Indent}}{{template "usage" .}}
39
+
40
+{{if .Arguments}}ARGUMENTS:
41
+
42
+{{.Indent}}{{.Arguments}}
43
+
44
+{{end}}{{if .Options}}OPTIONS:
45
+
46
+{{.Indent}}{{.Options}}
47
+
48
+{{end}}{{if .Subcommands}}SUBCOMMANDS:
49
+
50
+{{.Indent}}{{.Subcommands}}
51
+
52
+{{.Indent}}Use '{{.Path}} <subcmd> --help' for more information about each command.
53
+
54
+{{end}}{{if .Description}}DESCRIPTION:
55
+
56
+{{.Indent}}{{.Description}}
57
+
58
+{{end}}
59
+`
60
+
61
+var longHelpTemplate *template.Template
62
+var usageTemplate *template.Template
63
+
64
+func init() {
65
+ tmpl, err := template.New("usage").Parse(usageFormat)
66
if err != nil {
24
- return "", err
67
+ panic(err)
68
}
69
+ usageTemplate = tmpl
70
27
- s := ""
28
- usage := usageText(cmd)
29
- if len(usage) > 0 {
30
- usage += " "
71
+ tmpl, err = usageTemplate.New("longHelp").Parse(longHelpFormat)
72
+ if err != nil {
73
+ panic(err)
74
}
32
- s += fmt.Sprintf("%v %v %v- %v\n\n", rootName, strings.Join(path, " "), usage, cmd.Description)
75
+ longHelpTemplate = tmpl
76
+}
77
34
- if len(cmd.Help) > 0 {
35
- s += fmt.Sprintf("%v\n\n", strings.Trim(cmd.Help, whitespace))
78
+// LongHelp returns a formatted CLI helptext string, generated for the given command
79
+func LongHelp(rootName string, root *cmds.Command, path []string, out io.Writer) error {
80
+ cmd, err := root.Get(path)
81
+ if err != nil {
82
+ return err
83
}
84
38
- if cmd.Arguments != nil {
39
- if len(cmd.ArgumentHelp) > 0 {
40
- s += cmd.ArgumentHelp
41
- } else {
42
- section := strings.Join(indent(argumentText(cmd), " "), "\n")
43
- s += fmt.Sprintf("Arguments:\n%v", section)
44
- }
45
-
46
- s += "\n\n"
85
+ pathStr := rootName
86
+ if len(path) > 0 {
87
+ pathStr += " " + strings.Join(path, " ")
88
}
89
49
- if cmd.Subcommands != nil {
50
- if len(cmd.SubcommandHelp) > 0 {
51
- s += cmd.SubcommandHelp
52
- } else {
53
- section := strings.Join(indent(subcommandText(cmd, rootName, path), " "), "\n")
54
- s += fmt.Sprintf("Subcommands:\n%v", section)
55
- }
56
-
57
- s += "\n\n"
90
+ fields := helpFields{
91
+ Indent: indentStr,
92
+ Path: pathStr,
93
+ ArgUsage: usageText(cmd),
94
+ Tagline: cmd.Description,
95
+ Arguments: cmd.ArgumentHelp,
96
+ Options: cmd.OptionHelp,
97
+ Subcommands: cmd.SubcommandHelp,
98
+ Description: cmd.Help,
99
}
100
60
- if cmd.Options != nil {
61
- if len(cmd.OptionHelp) > 0 {
62
- s += cmd.OptionHelp
63
- } else {
64
- section := strings.Join(indent(optionText(cmd), " "), "\n")
65
- s += fmt.Sprintf("Options:\n%v", section)
66
- }
67
-
68
- s += "\n\n"
101
+ // autogen fields that are empty
102
+ if len(cmd.ArgumentHelp) == 0 {
103
+ fields.Arguments = strings.Join(argumentText(cmd), "\n")
104
+ }
105
+ if len(cmd.OptionHelp) == 0 {
106
+ fields.Options = strings.Join(optionText(cmd), "\n")
107
}
108
+ if len(cmd.SubcommandHelp) == 0 {
109
+ fields.Subcommands = strings.Join(subcommandText(cmd, rootName, path), "\n")
110
+ }
111
+
112
+ fields.Arguments = indentString(fields.Arguments, indentStr)
113
+ fields.Options = indentString(fields.Options, indentStr)
114
+ fields.Subcommands = indentString(fields.Subcommands, indentStr)
115
+ fields.Description = indentString(fields.Description, indentStr)
116
71
- return s, nil
117
+ return longHelpTemplate.Execute(out, fields)
118
}
119
120
func argumentText(cmd *cmds.Command) []string {