From 5c45e56898261c29ae44e65bd087a508c9abe0a5 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Fri, 12 Aug 2011 15:43:10 -0700
Subject: [PATCH] godoc: remove last vestiges of old template system
- rename template funcs for better consistency and
sort them into groups of related functionality
- try to be more consistent with html vs url escaping
R=r
CC=golang-dev
https://golang.org/cl/4887041
---
lib/godoc/godoc.html | 2 +-
lib/godoc/package.html | 50 +++---
lib/godoc/package.txt | 20 +--
lib/godoc/search.html | 41 ++---
lib/godoc/search.txt | 6 +-
src/cmd/godoc/godoc.go | 324 +++++++++++++++++----------------------
src/cmd/godoc/snippet.go | 9 +-
7 files changed, 200 insertions(+), 252 deletions(-)
diff --git a/lib/godoc/godoc.html b/lib/godoc/godoc.html
index 91e521258d6..e978b309c6e 100644
--- a/lib/godoc/godoc.html
+++ b/lib/godoc/godoc.html
@@ -25,7 +25,7 @@
@@ -27,58 +27,58 @@
{{with .Consts}}
Constants
{{range .}}
- {{html_comment .Doc}}
- {{html_node .Decl $.FSet}}
+ {{comment_html .Doc}}
+ {{node_html .Decl $.FSet}}
{{end}}
{{end}}
{{with .Vars}}
Variables
{{range .}}
- {{html_comment .Doc}}
- {{html_node .Decl $.FSet}}
+ {{comment_html .Doc}}
+ {{node_html .Decl $.FSet}}
{{end}}
{{end}}
{{with .Funcs}}
{{range .}}
{{/* Name is a string - no need for FSet */}}
{{$name := html .Name}}
-
- {{html_node .Decl $.FSet}}
- {{html_comment .Doc}}
+
+ {{node_html .Decl $.FSet}}
+ {{comment_html .Doc}}
{{end}}
{{end}}
{{with .Types}}
{{range .}}
- {{$tname := html_node .Type.Name $.FSet}}
-
- {{html_comment .Doc}}
- {{html_node .Decl $.FSet}}
+ {{$tname := node_html .Type.Name $.FSet}}
+
+ {{comment_html .Doc}}
+ {{node_html .Decl $.FSet}}
{{range .Consts}}
- {{html_comment .Doc}}
- {{html_node .Decl $.FSet}}
+ {{comment_html .Doc}}
+ {{node_html .Decl $.FSet}}
{{end}}
{{range .Vars}}
- {{html_comment .Doc}}
- {{html_node .Decl $.FSet}}
+ {{comment_html .Doc}}
+ {{node_html .Decl $.FSet}}
{{end}}
{{range .Factories}}
{{$name := html .Name}}
-
- {{html_node .Decl $.FSet}}
- {{html_comment .Doc}}
+
+ {{node_html .Decl $.FSet}}
+ {{comment_html .Doc}}
{{end}}
{{range .Methods}}
{{$name := html .Name}}
- func ({{html_node .Recv $.FSet}}) {{$name}}
- {{html_node .Decl $.FSet}}
- {{html_comment .Doc}}
+ func ({{node_html .Recv $.FSet}}) {{$name}}
+ {{node_html .Decl $.FSet}}
+ {{comment_html .Doc}}
{{end}}
{{end}}
{{end}}
{{with .Bugs}}
Bugs
{{range .}}
- {{html_comment .}}
+ {{comment_html .}}
{{end}}
{{end}}
{{end}}
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index af1a6306934..45c5566e8ce 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -2,7 +2,7 @@
---------------------------------------
-*/}}{{with .PAst}}{{text_node . $FSet}}{{end}}{{/*
+*/}}{{with .PAst}}{{node . $FSet}}{{end}}{{/*
---------------------------------------
@@ -16,7 +16,7 @@ import "{{.ImportPath}}"
---------------------------------------
-*/}}{{with .Doc}}{{text_node . $FSet}}
+*/}}{{with .Doc}}{{node . $FSet}}
{{end}}{{/*
---------------------------------------
@@ -24,7 +24,7 @@ import "{{.ImportPath}}"
*/}}{{with .Consts}}
CONSTANTS
-{{range .}}{{text_node .Decl $FSet}}
+{{range .}}{{node .Decl $FSet}}
{{.Doc}}{{end}}
{{end}}{{/*
@@ -33,7 +33,7 @@ CONSTANTS
*/}}{{with .Vars}}
VARIABLES
-{{range .}}{{text_node .Decl $FSet}}
+{{range .}}{{node .Decl $FSet}}
{{.Doc}}{{end}}
{{end}}{{/*
@@ -42,7 +42,7 @@ VARIABLES
*/}}{{with .Funcs}}
FUNCTIONS
-{{range .}}{{text_node .Decl $FSet}}
+{{range .}}{{node .Decl $FSet}}
{{.Doc}}
{{end}}{{end}}{{/*
@@ -51,15 +51,15 @@ FUNCTIONS
*/}}{{with .Types}}
TYPES
-{{range .}}{{text_node .Decl $FSet}}
+{{range .}}{{node .Decl $FSet}}
{{.Doc}}
-{{range .Consts}}{{text_node .Decl $FSet}}
+{{range .Consts}}{{node .Decl $FSet}}
{{.Doc}}
-{{end}}{{range .Vars}}{{text_node .Decl $FSet}}
+{{end}}{{range .Vars}}{{node .Decl $FSet}}
{{.Doc}}
-{{end}}{{range .Factories}}{{text_node .Decl $FSet}}
+{{end}}{{range .Factories}}{{node .Decl $FSet}}
{{.Doc}}
-{{end}}{{range .Methods}}{{text_node .Decl $FSet}}
+{{end}}{{range .Methods}}{{node .Decl $FSet}}
{{.Doc}}
{{end}}{{end}}{{end}}{{/*
diff --git a/lib/godoc/search.html b/lib/godoc/search.html
index 4c956721f83..39eec9b4983 100644
--- a/lib/godoc/search.html
+++ b/lib/godoc/search.html
@@ -3,10 +3,9 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
-{{$SearchResult := .}}
{{with .Alert}}
- {{.}}
+ {{html .}}
{{end}}
{{with .Alt}}
@@ -21,13 +20,14 @@
{{with .Decls}}
Package-level declarations
{{range .}}
-
+ {{$pkg := pkgLink .Pak.Path}}
+
{{range .Files}}
- {{$path := url_src .File.Path}}
+ {{$src := srcLink .File.Path}}
{{range .Groups}}
{{range .Infos}}
- {{$path}}:{{infoLine .}}
- {{infoSnippet .}}
+ {{html $src}}:{{infoLine .}}
+ {{infoSnippet_html .}}
{{end}}
{{end}}
{{end}}
@@ -36,19 +36,20 @@
{{with .Others}}
Local declarations and uses
{{range .}}
-
+ {{$pkg := pkgLink .Pak.Path}}
+
{{range .Files}}
- {{$path := url_src .File.Path}}
- {{$path}}
+ {{$src := srcLink .File.Path}}
+ {{html $src}}
{{range .Groups}}
|
- {{infoKind .Kind}} |
+ {{infoKind_html .Kind}} |
|
{{range .Infos}}
- {{infoLine .}}
+ {{infoLine .}}
{{end}}
|
@@ -59,36 +60,36 @@
{{end}}
{{end}}
{{with .Textual}}
- {{if $SearchResult.Complete}}
- {{html $SearchResult.Found}} textual occurrences
+ {{if $.Complete}}
+ {{html $.Found}} textual occurrences
{{else}}
- More than {{html $SearchResult.Found}} textual occurrences
+ More than {{html $.Found}} textual occurrences
- Not all files or lines containing "{{html $SearchResult.Query}}" are shown.
+ Not all files or lines containing "{{html $.Query}}" are shown.
{{end}}
{{range .}}
- {{$path := url_src .Filename}}
+ {{$src := srcLink .Filename}}
- {{$path}}:
+ {{html $src}}:
|
|
{{len .Lines}} |
|
{{range .Lines}}
- {{html .}}
+ {{html .}}
{{end}}
- {{if not $SearchResult.Complete}}
+ {{if not $.Complete}}
...
{{end}}
|
{{end}}
- {{if not $SearchResult.Complete}}
+ {{if not $.Complete}}
... |
{{end}}
diff --git a/lib/godoc/search.txt b/lib/godoc/search.txt
index 423712155aa..71343984c76 100644
--- a/lib/godoc/search.txt
+++ b/lib/godoc/search.txt
@@ -17,7 +17,7 @@ DID YOU MEAN
PACKAGE-LEVEL DECLARATIONS
{{range .}}package {{.Pak.Name}}
-{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{url_src $File.File.Path}}:{{infoLine .}}{{end}}
+{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{srcLink $File.File.Path}}:{{infoLine .}}{{end}}
{{end}}{{end}}{{/* .Files */}}
{{end}}{{end}}{{/* .Decls */}}{{/*
@@ -27,7 +27,7 @@ PACKAGE-LEVEL DECLARATIONS
LOCAL DECLARATIONS AND USES
{{range .}}package {{.Pak.Name}}
-{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{url_src $File.File.Path}}:{{infoLine .}}
+{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{srcLink $File.File.Path}}:{{infoLine .}}
{{end}}{{end}}{{end}}{{/* .Files */}}
{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
@@ -35,6 +35,6 @@ LOCAL DECLARATIONS AND USES
*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
-{{range .Textual}}{{len .Lines}} {{url_src .Filename}}
+{{range .Textual}}{{len .Lines}} {{srcLink .Filename}}
{{end}}{{if not .Complete}}... ...
{{end}}{{end}}
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index c70a03de821..15b60c72b08 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -371,176 +371,9 @@ func writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
(&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)
}
-func fileset(x []interface{}) *token.FileSet {
- if len(x) > 1 {
- if fset, ok := x[1].(*token.FileSet); ok {
- return fset
- }
- }
- return nil
-}
-
-// Template formatter for the various "url-xxx" formats excluding url-esc.
-func urlFmt(w io.Writer, format string, x ...interface{}) {
- var path string
- var line int
- var low, high int // selection
-
- // determine path and position info, if any
- type positioner interface {
- Pos() token.Pos
- End() token.Pos
- }
- switch t := x[0].(type) {
- case string:
- path = t
- case positioner:
- fset := fileset(x)
- if p := t.Pos(); p.IsValid() {
- pos := fset.Position(p)
- path = pos.Filename
- line = pos.Line
- low = pos.Offset
- }
- if p := t.End(); p.IsValid() {
- high = fset.Position(p).Offset
- }
- default:
- // we should never reach here, but be resilient
- // and assume the position is invalid (empty path,
- // and line 0)
- log.Printf("INTERNAL ERROR: urlFmt(%s) without a string or positioner", format)
- }
-
- // map path
- relpath := relativeURL(path)
-
- // convert to relative URLs so that they can also
- // be used as relative file names in .txt templates
- switch format {
- default:
- // we should never reach here, but be resilient
- // and assume the url-pkg format instead
- log.Printf("INTERNAL ERROR: urlFmt(%s)", format)
- fallthrough
- case "url_pkg":
- // because of the irregular mapping under goroot
- // we need to correct certain relative paths
- if strings.HasPrefix(relpath, "src/pkg/") {
- relpath = relpath[len("src/pkg/"):]
- }
- template.HTMLEscape(w, []byte(pkgHandler.pattern[1:]+relpath)) // remove trailing '/' for relative URL
- case "url_src":
- template.HTMLEscape(w, []byte(relpath))
- case "url_pos":
- template.HTMLEscape(w, []byte(relpath))
- // selection ranges are of form "s=low:high"
- if low < high {
- fmt.Fprintf(w, "?s=%d:%d", low, high)
- // if we have a selection, position the page
- // such that the selection is a bit below the top
- line -= 10
- if line < 1 {
- line = 1
- }
- }
- // line id's in html-printed source are of the
- // form "L%d" where %d stands for the line number
- if line > 0 {
- fmt.Fprintf(w, "#L%d", line)
- }
- }
-}
-
-// The strings in infoKinds must be properly html-escaped.
-var infoKinds = [nKinds]string{
- PackageClause: "package clause",
- ImportDecl: "import decl",
- ConstDecl: "const decl",
- TypeDecl: "type decl",
- VarDecl: "var decl",
- FuncDecl: "func decl",
- MethodDecl: "method decl",
- Use: "use",
-}
-
-// Template formatter for "infoKind" format.
-func infoKindFmt(w io.Writer, format string, x ...interface{}) {
- fmt.Fprintf(w, infoKinds[x[0].(SpotKind)]) // infoKind entries are html-escaped
-}
-
-// Template formatter for "infoLine" format.
-func infoLineFmt(w io.Writer, format string, x ...interface{}) {
- info := x[0].(SpotInfo)
- line := info.Lori()
- if info.IsIndex() {
- index, _ := searchIndex.get()
- if index != nil {
- line = index.(*Index).Snippet(line).Line
- } else {
- // no line information available because
- // we don't have an index - this should
- // never happen; be conservative and don't
- // crash
- line = 0
- }
- }
- fmt.Fprintf(w, "%d", line)
-}
-
-// Template formatter for "infoSnippet" format.
-func infoSnippetFmt(w io.Writer, format string, x ...interface{}) {
- info := x[0].(SpotInfo)
- text := []byte(`no snippet text available`)
- if info.IsIndex() {
- index, _ := searchIndex.get()
- // no escaping of snippet text needed;
- // snippet text is escaped when generated
- text = index.(*Index).Snippet(info.Lori()).Text
- }
- w.Write(text)
-}
-
-// TODO(gri): Remove this type once fmtMap2funcMap is gone.
-type FormatterMap map[string]func(io.Writer, string, ...interface{})
-
-// TODO(gri): Remove the need for this conversion function by rewriting
-// the old template formatters into new template functions.
-func append2funcMap(funcMap template.FuncMap, fmtMap FormatterMap) template.FuncMap {
- for n, f := range fmtMap {
- name, fmt := n, f // separate instance of name, fmt for each closure!
- if _, ok := funcMap[name]; ok {
- panic("function already in map: " + name)
- }
- funcMap[name] = func(args ...interface{}) string {
- var buf bytes.Buffer
- fmt(&buf, name, args...)
- return buf.String()
- }
- }
- return funcMap
-}
-
-func textNodeFunc(node interface{}, fset *token.FileSet) string {
- var buf bytes.Buffer
- writeNode(&buf, fset, node)
- return buf.String()
-}
-
-func htmlNodeFunc(node interface{}, fset *token.FileSet) string {
- var buf1 bytes.Buffer
- writeNode(&buf1, fset, node)
- var buf2 bytes.Buffer
- FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
- return buf2.String()
-}
-
-func htmlCommentFunc(comment string) string {
- var buf bytes.Buffer
- // TODO(gri) Provide list of words (e.g. function parameters)
- // to be emphasized by ToHTML.
- doc.ToHTML(&buf, []byte(comment), nil) // does html-escaping
- return buf.String()
+func filenameFunc(path string) string {
+ _, localname := filepath.Split(path)
+ return localname
}
func fileInfoNameFunc(fi FileInfo) string {
@@ -558,27 +391,144 @@ func fileInfoTimeFunc(fi FileInfo) string {
return "" // don't return epoch if time is obviously not set
}
-func localnameFunc(path string) string {
- _, localname := filepath.Split(path)
- return localname
+// The strings in infoKinds must be properly html-escaped.
+var infoKinds = [nKinds]string{
+ PackageClause: "package clause",
+ ImportDecl: "import decl",
+ ConstDecl: "const decl",
+ TypeDecl: "type decl",
+ VarDecl: "var decl",
+ FuncDecl: "func decl",
+ MethodDecl: "method decl",
+ Use: "use",
}
-var fmap = append2funcMap(template.FuncMap{
- "text_node": textNodeFunc,
- "html_node": htmlNodeFunc,
- "html_comment": htmlCommentFunc,
+func infoKind_htmlFunc(kind SpotKind) string {
+ return infoKinds[kind] // infoKind entries are html-escaped
+}
+
+func infoLineFunc(info SpotInfo) int {
+ line := info.Lori()
+ if info.IsIndex() {
+ index, _ := searchIndex.get()
+ if index != nil {
+ line = index.(*Index).Snippet(line).Line
+ } else {
+ // no line information available because
+ // we don't have an index - this should
+ // never happen; be conservative and don't
+ // crash
+ line = 0
+ }
+ }
+ return line
+}
+
+func infoSnippet_htmlFunc(info SpotInfo) string {
+ if info.IsIndex() {
+ index, _ := searchIndex.get()
+ // Snippet.Text was HTML-escaped when it was generated
+ return index.(*Index).Snippet(info.Lori()).Text
+ }
+ return `no snippet text available`
+}
+
+func nodeFunc(node interface{}, fset *token.FileSet) string {
+ var buf bytes.Buffer
+ writeNode(&buf, fset, node)
+ return buf.String()
+}
+
+func node_htmlFunc(node interface{}, fset *token.FileSet) string {
+ var buf1 bytes.Buffer
+ writeNode(&buf1, fset, node)
+ var buf2 bytes.Buffer
+ FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
+ return buf2.String()
+}
+
+func comment_htmlFunc(comment string) string {
+ var buf bytes.Buffer
+ // TODO(gri) Provide list of words (e.g. function parameters)
+ // to be emphasized by ToHTML.
+ doc.ToHTML(&buf, []byte(comment), nil) // does html-escaping
+ return buf.String()
+}
+
+func pkgLinkFunc(path string) string {
+ relpath := relativeURL(path)
+ // because of the irregular mapping under goroot
+ // we need to correct certain relative paths
+ if strings.HasPrefix(relpath, "src/pkg/") {
+ relpath = relpath[len("src/pkg/"):]
+ }
+ return pkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL
+}
+
+func posLinkFunc(node ast.Node, fset *token.FileSet) string {
+ var relpath string
+ var line int
+ var low, high int // selection
+
+ if p := node.Pos(); p.IsValid() {
+ pos := fset.Position(p)
+ relpath = relativeURL(pos.Filename)
+ line = pos.Line
+ low = pos.Offset
+ }
+ if p := node.End(); p.IsValid() {
+ high = fset.Position(p).Offset
+ }
+
+ var buf bytes.Buffer
+ buf.WriteString(relpath)
+ // selection ranges are of form "s=low:high"
+ if low < high {
+ fmt.Fprintf(&buf, "?s=%d:%d", low, high)
+ // if we have a selection, position the page
+ // such that the selection is a bit below the top
+ line -= 10
+ if line < 1 {
+ line = 1
+ }
+ }
+ // line id's in html-printed source are of the
+ // form "L%d" where %d stands for the line number
+ if line > 0 {
+ fmt.Fprintf(&buf, "#L%d", line)
+ }
+
+ return buf.String()
+}
+
+// fmap describes the template functions installed with all godoc templates.
+// Convention: template function names ending in "_html" produce an HTML-
+// escaped string; all other function results may require HTML
+// or URL escaping in the template.
+var fmap = template.FuncMap{
+ // various helpers
+ "filename": filenameFunc,
+ "repeat": strings.Repeat,
+
+ // accss to FileInfos (directory listings)
"fileInfoName": fileInfoNameFunc,
"fileInfoTime": fileInfoTimeFunc,
- "localname": localnameFunc,
- "repeat": strings.Repeat,
-}, FormatterMap{
- "url_pkg": urlFmt,
- "url_src": urlFmt,
- "url_pos": urlFmt,
- "infoKind": infoKindFmt,
- "infoLine": infoLineFmt,
- "infoSnippet": infoSnippetFmt,
-})
+
+ // access to search result information
+ "infoKind_html": infoKind_htmlFunc,
+ "infoLine": infoLineFunc,
+ "infoSnippet_html": infoSnippet_htmlFunc,
+
+ // formatting of AST nodes
+ "node": nodeFunc,
+ "node_html": node_htmlFunc,
+ "comment_html": comment_htmlFunc,
+
+ // support for URL attributes
+ "pkgLink": pkgLinkFunc,
+ "srcLink": relativeURL,
+ "posLink": posLinkFunc,
+}
func readTemplate(name string) *template.Template {
path := filepath.Join(*goroot, "lib", "godoc", name)
diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go
index 626b01455dd..68e27d9a0cb 100755
--- a/src/cmd/godoc/snippet.go
+++ b/src/cmd/godoc/snippet.go
@@ -18,7 +18,7 @@ import (
type Snippet struct {
Line int
- Text []byte
+ Text string // HTML-escaped
}
func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
@@ -30,7 +30,7 @@ func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
buf2.WriteString("")
FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil)
buf2.WriteString("
")
- return &Snippet{fset.Position(id.Pos()).Line, buf2.Bytes()}
+ return &Snippet{fset.Position(id.Pos()).Line, buf2.String()}
}
func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
@@ -94,10 +94,7 @@ func NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) (s *Snippet)
if s == nil {
var buf bytes.Buffer
fmt.Fprintf(&buf, `could not generate a snippet for %s`, id.Name)
- s = &Snippet{
- fset.Position(id.Pos()).Line,
- buf.Bytes(),
- }
+ s = &Snippet{fset.Position(id.Pos()).Line, buf.String()}
}
return
}