libgo: update to Go 1.11
[official-gcc.git] / libgo / go / cmd / go / internal / help / help.go
bloba80afe36c412c4de955f36f21fa60e13b7eeb18b
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"
22 // Help implements the 'help' command.
23 func Help(args []string) {
24 // 'go help documentation' generates doc.go.
25 if len(args) == 1 && args[0] == "documentation" {
26 fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.")
27 fmt.Println("// Use of this source code is governed by a BSD-style")
28 fmt.Println("// license that can be found in the LICENSE file.")
29 fmt.Println()
30 fmt.Println("// Code generated by mkalldocs.sh; DO NOT EDIT.")
31 fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
32 fmt.Println()
33 buf := new(bytes.Buffer)
34 PrintUsage(buf, base.Go)
35 usage := &base.Command{Long: buf.String()}
36 cmds := []*base.Command{usage}
37 for _, cmd := range base.Go.Commands {
38 if cmd.UsageLine == "gopath-get" {
39 // Avoid duplication of the "get" documentation.
40 continue
42 cmds = append(cmds, cmd)
43 cmds = append(cmds, cmd.Commands...)
45 tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, cmds)
46 fmt.Println("package main")
47 return
50 cmd := base.Go
51 Args:
52 for i, arg := range args {
53 for _, sub := range cmd.Commands {
54 if sub.Name() == arg {
55 cmd = sub
56 continue Args
60 // helpSuccess is the help command using as many args as possible that would succeed.
61 helpSuccess := "go help"
62 if i > 0 {
63 helpSuccess = " " + strings.Join(args[:i], " ")
65 fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
66 os.Exit(2) // failed at 'go help cmd'
69 if len(cmd.Commands) > 0 {
70 PrintUsage(os.Stdout, cmd)
71 } else {
72 tmpl(os.Stdout, helpTemplate, cmd)
74 // not exit 2: succeeded at 'go help cmd'.
75 return
78 var usageTemplate = `{{.Long | trim}}
80 Usage:
82 {{.UsageLine}} <command> [arguments]
84 The commands are:
85 {{range .Commands}}{{if or (.Runnable) .Commands}}
86 {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
88 Use "go help{{with .LongName}} {{.}}{{end}} <command>" for more information about a command.
89 {{if eq (.UsageLine) "go"}}
90 Additional help topics:
91 {{range .Commands}}{{if and (not .Runnable) (not .Commands)}}
92 {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
94 Use "go help{{with .LongName}} {{.}}{{end}} <topic>" for more information about that topic.
95 {{end}}
98 var helpTemplate = `{{if .Runnable}}usage: {{.UsageLine}}
100 {{end}}{{.Long | trim}}
103 var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
105 {{end}}{{if .Commands}}` + usageTemplate + `{{else}}{{if .Runnable}}Usage:
107 {{.UsageLine}}
109 {{end}}{{.Long | trim}}
112 {{end}}{{end}}`
114 // commentWriter writes a Go comment to the underlying io.Writer,
115 // using line comment form (//).
116 type commentWriter struct {
117 W io.Writer
118 wroteSlashes bool // Wrote "//" at the beginning of the current line.
121 func (c *commentWriter) Write(p []byte) (int, error) {
122 var n int
123 for i, b := range p {
124 if !c.wroteSlashes {
125 s := "//"
126 if b != '\n' {
127 s = "// "
129 if _, err := io.WriteString(c.W, s); err != nil {
130 return n, err
132 c.wroteSlashes = true
134 n0, err := c.W.Write(p[i : i+1])
135 n += n0
136 if err != nil {
137 return n, err
139 if b == '\n' {
140 c.wroteSlashes = false
143 return len(p), nil
146 // An errWriter wraps a writer, recording whether a write error occurred.
147 type errWriter struct {
148 w io.Writer
149 err error
152 func (w *errWriter) Write(b []byte) (int, error) {
153 n, err := w.w.Write(b)
154 if err != nil {
155 w.err = err
157 return n, err
160 // tmpl executes the given template text on data, writing the result to w.
161 func tmpl(w io.Writer, text string, data interface{}) {
162 t := template.New("top")
163 t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
164 template.Must(t.Parse(text))
165 ew := &errWriter{w: w}
166 err := t.Execute(ew, data)
167 if ew.err != nil {
168 // I/O error writing. Ignore write on closed pipe.
169 if strings.Contains(ew.err.Error(), "pipe") {
170 os.Exit(1)
172 base.Fatalf("writing output: %v", ew.err)
174 if err != nil {
175 panic(err)
179 func capitalize(s string) string {
180 if s == "" {
181 return s
183 r, n := utf8.DecodeRuneInString(s)
184 return string(unicode.ToTitle(r)) + s[n:]
187 func PrintUsage(w io.Writer, cmd *base.Command) {
188 bw := bufio.NewWriter(w)
189 tmpl(bw, usageTemplate, cmd)
190 bw.Flush()