diff options
Diffstat (limited to 'doc/tmpltohtml.go')
| -rw-r--r-- | doc/tmpltohtml.go | 199 |
1 files changed, 0 insertions, 199 deletions
diff --git a/doc/tmpltohtml.go b/doc/tmpltohtml.go deleted file mode 100644 index 70745f4dd..000000000 --- a/doc/tmpltohtml.go +++ /dev/null @@ -1,199 +0,0 @@ -// 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. - -// 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 main - -import ( - "flag" - "fmt" - "io/ioutil" - "log" - "os" - "path/filepath" - "regexp" - "strings" - "text/template" -) - -func Usage() { - fmt.Fprintf(os.Stderr, "usage: tmpltohtml file\n") - os.Exit(2) -} - -var templateFuncs = template.FuncMap{ - "code": code, - "donotedit": donotedit, -} - -func main() { - flag.Usage = Usage - flag.Parse() - if len(flag.Args()) != 1 { - Usage() - } - - // Read and parse the input. - name := flag.Arg(0) - tmpl := template.New(filepath.Base(name)).Funcs(templateFuncs) - if _, err := tmpl.ParseFiles(name); err != nil { - log.Fatal(err) - } - - // Execute the template. - if err := tmpl.Execute(os.Stdout, 0); err != nil { - log.Fatal(err) - } -} - -// contents reads a file by name and returns its contents as a string. -func contents(name string) string { - file, err := ioutil.ReadFile(name) - if err != nil { - log.Fatal(err) - } - return string(file) -} - -// format returns a textual representation of the arg, formatted according to its nature. -func format(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.Fatalf("unrecognized argument: %v type %T", arg, arg) - } - return "" -} - -func donotedit() string { - // No editing please. - return fmt.Sprintf("<!--\n DO NOT EDIT: created by\n tmpltohtml %s\n-->\n", flag.Args()[0]) -} - -func code(file string, arg ...interface{}) (string, error) { - text := 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, format(arg[0])) - text = oneLine(file, text, arg[0]) - case 2: - command = fmt.Sprintf("code %q %s %s", file, format(arg[0]), format(arg[1])) - text = multipleLines(file, text, arg[0], arg[1]) - default: - return "", fmt.Errorf("incorrect code invocation: code %q %q", file, 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) - // Escape the program text for HTML. - text = template.HTMLEscapeString(text) - // Include the command as a comment. - text = fmt.Sprintf("<pre><!--{{%s}}\n-->%s</pre>", command, text) - 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.Fatalf("%q:%d is out of range", file, n) - } - return n, "", true - case string: - return 0, n, false - } - log.Fatalf("unrecognized argument %v type %T", arg, arg) - return -} - -// oneLine returns the single line generated by a two-argument code invocation. -func oneLine(file, text string, arg interface{}) string { - lines := strings.SplitAfter(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 multipleLines(file, text string, arg1, arg2 interface{}) string { - lines := strings.SplitAfter(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.Fatalf("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.Fatalf("%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.Fatal(err) - } - for i := start; i < len(lines); i++ { - if re.MatchString(lines[i]) { - return i + 1 - } - } - log.Fatalf("%s: no match for %#q", file, pattern) - } - log.Fatalf("unrecognized pattern: %q", pattern) - return 0 -} |
