complex-lowering: Better handling of PAREN_EXPR [PR68855]
[official-gcc.git] / libgo / go / cmd / go / internal / help / help.go
blob2a07d2423bdd9e46eb397228214cde2b13226695
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package help implements the ``go help'' command.
6 package help
8 import (
9 "bufio"
10 "bytes"
11 "fmt"
12 "io"
13 "os"
14 "strings"
15 "text/template"
16 "unicode"
17 "unicode/utf8"
19 "cmd/go/internal/base"
20 "cmd/go/internal/modload"
23 // Help implements the 'help' command.
24 func Help(w io.Writer, args []string) {
25 // 'go help documentation' generates doc.go.
26 if len(args) == 1 && args[0] == "documentation" {
27 fmt.Fprintln(w, "// Copyright 2011 The Go Authors. All rights reserved.")
28 fmt.Fprintln(w, "// Use of this source code is governed by a BSD-style")
29 fmt.Fprintln(w, "// license that can be found in the LICENSE file.")
30 fmt.Fprintln(w)
31 fmt.Fprintln(w, "// Code generated by mkalldocs.sh; DO NOT EDIT.")
32 fmt.Fprintln(w, "// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
33 fmt.Fprintln(w)
34 buf := new(bytes.Buffer)
35 PrintUsage(buf, base.Go)
36 usage := &base.Command{Long: buf.String()}
37 cmds := []*base.Command{usage}
38 for _, cmd := range base.Go.Commands {
39 // Avoid duplication of the "get" documentation.
40 if cmd.UsageLine == "module-get" && modload.Enabled() {
41 continue
42 } else if cmd.UsageLine == "gopath-get" && !modload.Enabled() {
43 continue
45 cmds = append(cmds, cmd)
46 cmds = append(cmds, cmd.Commands...)
48 tmpl(&commentWriter{W: w}, documentationTemplate, cmds)
49 fmt.Fprintln(w, "package main")
50 return
53 cmd := base.Go
54 Args:
55 for i, arg := range args {
56 for _, sub := range cmd.Commands {
57 if sub.Name() == arg {
58 cmd = sub
59 continue Args
63 // helpSuccess is the help command using as many args as possible that would succeed.
64 helpSuccess := "go help"
65 if i > 0 {
66 helpSuccess += " " + strings.Join(args[:i], " ")
68 fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
69 base.SetExitStatus(2) // failed at 'go help cmd'
70 base.Exit()
73 if len(cmd.Commands) > 0 {
74 PrintUsage(os.Stdout, cmd)
75 } else {
76 tmpl(os.Stdout, helpTemplate, cmd)
78 // not exit 2: succeeded at 'go help cmd'.
79 return
82 var usageTemplate = `{{.Long | trim}}
84 Usage:
86 {{.UsageLine}} <command> [arguments]
88 The commands are:
89 {{range .Commands}}{{if or (.Runnable) .Commands}}
90 {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
92 Use "go help{{with .LongName}} {{.}}{{end}} <command>" for more information about a command.
93 {{if eq (.UsageLine) "go"}}
94 Additional help topics:
95 {{range .Commands}}{{if and (not .Runnable) (not .Commands)}}
96 {{.Name | printf "%-15s"}} {{.Short}}{{end}}{{end}}
98 Use "go help{{with .LongName}} {{.}}{{end}} <topic>" for more information about that topic.
99 {{end}}
102 var helpTemplate = `{{if .Runnable}}usage: {{.UsageLine}}
104 {{end}}{{.Long | trim}}
107 var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
109 {{end}}{{if .Commands}}` + usageTemplate + `{{else}}{{if .Runnable}}Usage:
111 {{.UsageLine}}
113 {{end}}{{.Long | trim}}
116 {{end}}{{end}}`
118 // commentWriter writes a Go comment to the underlying io.Writer,
119 // using line comment form (//).
120 type commentWriter struct {
121 W io.Writer
122 wroteSlashes bool // Wrote "//" at the beginning of the current line.
125 func (c *commentWriter) Write(p []byte) (int, error) {
126 var n int
127 for i, b := range p {
128 if !c.wroteSlashes {
129 s := "//"
130 if b != '\n' {
131 s = "// "
133 if _, err := io.WriteString(c.W, s); err != nil {
134 return n, err
136 c.wroteSlashes = true
138 n0, err := c.W.Write(p[i : i+1])
139 n += n0
140 if err != nil {
141 return n, err
143 if b == '\n' {
144 c.wroteSlashes = false
147 return len(p), nil
150 // An errWriter wraps a writer, recording whether a write error occurred.
151 type errWriter struct {
152 w io.Writer
153 err error
156 func (w *errWriter) Write(b []byte) (int, error) {
157 n, err := w.w.Write(b)
158 if err != nil {
159 w.err = err
161 return n, err
164 // tmpl executes the given template text on data, writing the result to w.
165 func tmpl(w io.Writer, text string, data any) {
166 t := template.New("top")
167 t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
168 template.Must(t.Parse(text))
169 ew := &errWriter{w: w}
170 err := t.Execute(ew, data)
171 if ew.err != nil {
172 // I/O error writing. Ignore write on closed pipe.
173 if strings.Contains(ew.err.Error(), "pipe") {
174 base.SetExitStatus(1)
175 base.Exit()
177 base.Fatalf("writing output: %v", ew.err)
179 if err != nil {
180 panic(err)
184 func capitalize(s string) string {
185 if s == "" {
186 return s
188 r, n := utf8.DecodeRuneInString(s)
189 return string(unicode.ToTitle(r)) + s[n:]
192 func PrintUsage(w io.Writer, cmd *base.Command) {
193 bw := bufio.NewWriter(w)
194 tmpl(bw, usageTemplate, cmd)
195 bw.Flush()