Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / godoc / template.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/godoc/template.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/godoc/template.go
new file mode 100644 (file)
index 0000000..1e4e42e
--- /dev/null
@@ -0,0 +1,179 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Template support for writing HTML documents.
+// Documents that include Template: true in their
+// metadata are executed as input to text/template.
+//
+// This file defines functions for those templates to invoke.
+
+// The template uses the function "code" to inject program
+// source into the output by extracting code from files and
+// injecting them as HTML-escaped <pre> blocks.
+//
+// The syntax is simple: 1, 2, or 3 space-separated arguments:
+//
+// Whole file:
+//     {{code "foo.go"}}
+// One line (here the signature of main):
+//     {{code "foo.go" `/^func.main/`}}
+// Block of text, determined by start and end (here the body of main):
+//     {{code "foo.go" `/^func.main/` `/^}/`
+//
+// Patterns can be `/regular expression/`, a decimal number, or "$"
+// to signify the end of the file. In multi-line matches,
+// lines that end with the four characters
+//     OMIT
+// are omitted from the output, making it easy to provide marker
+// lines in the input that will not appear in the output but are easy
+// to identify by pattern.
+
+package godoc
+
+import (
+       "bytes"
+       "fmt"
+       "log"
+       "regexp"
+       "strings"
+
+       "golang.org/x/tools/godoc/vfs"
+)
+
+// Functions in this file panic on error, but the panic is recovered
+// to an error by 'code'.
+
+// contents reads and returns the content of the named file
+// (from the virtual file system, so for example /doc refers to $GOROOT/doc).
+func (c *Corpus) contents(name string) string {
+       file, err := vfs.ReadFile(c.fs, name)
+       if err != nil {
+               log.Panic(err)
+       }
+       return string(file)
+}
+
+// stringFor returns a textual representation of the arg, formatted according to its nature.
+func stringFor(arg interface{}) string {
+       switch arg := arg.(type) {
+       case int:
+               return fmt.Sprintf("%d", arg)
+       case string:
+               if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
+                       return fmt.Sprintf("%#q", arg)
+               }
+               return fmt.Sprintf("%q", arg)
+       default:
+               log.Panicf("unrecognized argument: %v type %T", arg, arg)
+       }
+       return ""
+}
+
+func (p *Presentation) code(file string, arg ...interface{}) (s string, err error) {
+       defer func() {
+               if r := recover(); r != nil {
+                       err = fmt.Errorf("%v", r)
+               }
+       }()
+
+       text := p.Corpus.contents(file)
+       var command string
+       switch len(arg) {
+       case 0:
+               // text is already whole file.
+               command = fmt.Sprintf("code %q", file)
+       case 1:
+               command = fmt.Sprintf("code %q %s", file, stringFor(arg[0]))
+               text = p.Corpus.oneLine(file, text, arg[0])
+       case 2:
+               command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
+               text = p.Corpus.multipleLines(file, text, arg[0], arg[1])
+       default:
+               return "", fmt.Errorf("incorrect code invocation: code %q [%v, ...] (%d arguments)", file, arg[0], len(arg))
+       }
+       // Trim spaces from output.
+       text = strings.Trim(text, "\n")
+       // Replace tabs by spaces, which work better in HTML.
+       text = strings.Replace(text, "\t", "    ", -1)
+       var buf bytes.Buffer
+       // HTML-escape text and syntax-color comments like elsewhere.
+       FormatText(&buf, []byte(text), -1, true, "", nil)
+       // Include the command as a comment.
+       text = fmt.Sprintf("<pre><!--{{%s}}\n-->%s</pre>", command, buf.Bytes())
+       return text, nil
+}
+
+// parseArg returns the integer or string value of the argument and tells which it is.
+func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
+       switch n := arg.(type) {
+       case int:
+               if n <= 0 || n > max {
+                       log.Panicf("%q:%d is out of range", file, n)
+               }
+               return n, "", true
+       case string:
+               return 0, n, false
+       }
+       log.Panicf("unrecognized argument %v type %T", arg, arg)
+       return
+}
+
+// oneLine returns the single line generated by a two-argument code invocation.
+func (c *Corpus) oneLine(file, text string, arg interface{}) string {
+       lines := strings.SplitAfter(c.contents(file), "\n")
+       line, pattern, isInt := parseArg(arg, file, len(lines))
+       if isInt {
+               return lines[line-1]
+       }
+       return lines[match(file, 0, lines, pattern)-1]
+}
+
+// multipleLines returns the text generated by a three-argument code invocation.
+func (c *Corpus) multipleLines(file, text string, arg1, arg2 interface{}) string {
+       lines := strings.SplitAfter(c.contents(file), "\n")
+       line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
+       line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
+       if !isInt1 {
+               line1 = match(file, 0, lines, pattern1)
+       }
+       if !isInt2 {
+               line2 = match(file, line1, lines, pattern2)
+       } else if line2 < line1 {
+               log.Panicf("lines out of order for %q: %d %d", text, line1, line2)
+       }
+       for k := line1 - 1; k < line2; k++ {
+               if strings.HasSuffix(lines[k], "OMIT\n") {
+                       lines[k] = ""
+               }
+       }
+       return strings.Join(lines[line1-1:line2], "")
+}
+
+// match identifies the input line that matches the pattern in a code invocation.
+// If start>0, match lines starting there rather than at the beginning.
+// The return value is 1-indexed.
+func match(file string, start int, lines []string, pattern string) int {
+       // $ matches the end of the file.
+       if pattern == "$" {
+               if len(lines) == 0 {
+                       log.Panicf("%q: empty file", file)
+               }
+               return len(lines)
+       }
+       // /regexp/ matches the line that matches the regexp.
+       if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
+               re, err := regexp.Compile(pattern[1 : len(pattern)-1])
+               if err != nil {
+                       log.Panic(err)
+               }
+               for i := start; i < len(lines); i++ {
+                       if re.MatchString(lines[i]) {
+                               return i + 1
+                       }
+               }
+               log.Panicf("%s: no match for %#q", file, pattern)
+       }
+       log.Panicf("unrecognized pattern: %q", pattern)
+       return 0
+}