...
1
2
3
4
5
6 package help
7
8 import (
9 "bufio"
10 "fmt"
11 "io"
12 "os"
13 "strings"
14 "text/template"
15 "unicode"
16 "unicode/utf8"
17
18 "cmd/go/internal/base"
19 )
20
21
22 func Help(w io.Writer, args []string) {
23
24 if len(args) == 1 && args[0] == "documentation" {
25 fmt.Fprintln(w, "// Copyright 2011 The Go Authors. All rights reserved.")
26 fmt.Fprintln(w, "// Use of this source code is governed by a BSD-style")
27 fmt.Fprintln(w, "// license that can be found in the LICENSE file.")
28 fmt.Fprintln(w)
29 fmt.Fprintln(w, "// Code generated by 'go test cmd/go -v -run=^TestDocsUpToDate$ -fixdocs'; DO NOT EDIT.")
30 fmt.Fprintln(w, "// Edit the documentation in other files and then execute 'go generate cmd/go' to generate this one.")
31 fmt.Fprintln(w)
32 buf := new(strings.Builder)
33 PrintUsage(buf, base.Go)
34 usage := &base.Command{Long: buf.String()}
35 cmds := []*base.Command{usage}
36 for _, cmd := range base.Go.Commands {
37 cmds = append(cmds, cmd)
38 cmds = append(cmds, cmd.Commands...)
39 }
40 tmpl(&commentWriter{W: w}, documentationTemplate, cmds)
41 fmt.Fprintln(w, "package main")
42 return
43 }
44
45 cmd := base.Go
46 Args:
47 for i, arg := range args {
48 for _, sub := range cmd.Commands {
49 if sub.Name() == arg {
50 cmd = sub
51 continue Args
52 }
53 }
54
55
56 helpSuccess := "go help"
57 if i > 0 {
58 helpSuccess += " " + strings.Join(args[:i], " ")
59 }
60 fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
61 base.SetExitStatus(2)
62 base.Exit()
63 }
64
65 if len(cmd.Commands) > 0 {
66 PrintUsage(os.Stdout, cmd)
67 } else {
68 tmpl(os.Stdout, helpTemplate, cmd)
69 }
70
71 return
72 }
73
74 var usageTemplate = `{{.Long | trim}}
75
76 Usage:
77
78 {{.UsageLine}} <command> [arguments]
79
80 The commands are:
81 {{range .Commands}}{{if or (.Runnable) .Commands}}
82 {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
83
84 Use "go help{{with .LongName}} {{.}}{{end}} <command>" for more information about a command.
85 {{if eq (.UsageLine) "go"}}
86 Additional help topics:
87 {{range .Commands}}{{if and (not .Runnable) (not .Commands)}}
88 {{.Name | printf "%-15s"}} {{.Short}}{{end}}{{end}}
89
90 Use "go help{{with .LongName}} {{.}}{{end}} <topic>" for more information about that topic.
91 {{end}}
92 `
93
94 var helpTemplate = `{{if .Runnable}}usage: {{.UsageLine}}
95
96 {{end}}{{.Long | trim}}
97 `
98
99 var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
100
101 {{end}}{{if .Commands}}` + usageTemplate + `{{else}}{{if .Runnable}}Usage:
102
103 {{.UsageLine}}
104
105 {{end}}{{.Long | trim}}
106
107
108 {{end}}{{end}}`
109
110
111
112 type commentWriter struct {
113 W io.Writer
114 wroteSlashes bool
115 }
116
117 func (c *commentWriter) Write(p []byte) (int, error) {
118 var n int
119 for i, b := range p {
120 if !c.wroteSlashes {
121 s := "//"
122 if b != '\n' {
123 s = "// "
124 }
125 if _, err := io.WriteString(c.W, s); err != nil {
126 return n, err
127 }
128 c.wroteSlashes = true
129 }
130 n0, err := c.W.Write(p[i : i+1])
131 n += n0
132 if err != nil {
133 return n, err
134 }
135 if b == '\n' {
136 c.wroteSlashes = false
137 }
138 }
139 return len(p), nil
140 }
141
142
143 type errWriter struct {
144 w io.Writer
145 err error
146 }
147
148 func (w *errWriter) Write(b []byte) (int, error) {
149 n, err := w.w.Write(b)
150 if err != nil {
151 w.err = err
152 }
153 return n, err
154 }
155
156
157 func tmpl(w io.Writer, text string, data any) {
158 t := template.New("top")
159 t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
160 template.Must(t.Parse(text))
161 ew := &errWriter{w: w}
162 err := t.Execute(ew, data)
163 if ew.err != nil {
164
165 if strings.Contains(ew.err.Error(), "pipe") {
166 base.SetExitStatus(1)
167 base.Exit()
168 }
169 base.Fatalf("writing output: %v", ew.err)
170 }
171 if err != nil {
172 panic(err)
173 }
174 }
175
176 func capitalize(s string) string {
177 if s == "" {
178 return s
179 }
180 r, n := utf8.DecodeRuneInString(s)
181 return string(unicode.ToTitle(r)) + s[n:]
182 }
183
184 func PrintUsage(w io.Writer, cmd *base.Command) {
185 bw := bufio.NewWriter(w)
186 tmpl(bw, usageTemplate, cmd)
187 bw.Flush()
188 }
189
View as plain text