1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:14:41 -07:00

godoc: first round of template cleanups

- simplified pipelines
- simplified templates by using template variables
- converted most old-style formatters into new-style funcs
- fixed some escaping bugs (use of url escaping where it was missing)

R=r, dsymonds
CC=golang-dev
https://golang.org/cl/4868044
This commit is contained in:
Robert Griesemer 2011-08-12 10:06:32 -07:00
parent 4abbdc0399
commit 5233c50321
11 changed files with 150 additions and 201 deletions

View File

@ -19,7 +19,7 @@
</a> </a>
<select id="code-selector"> <select id="code-selector">
{{range .File}} {{range .File}}
<option value="/doc/codewalk/?fileprint=/{{.|urlquery_esc}}">{{.|html_esc}}</option> <option value="/doc/codewalk/?fileprint=/{{url .}}">{{html .}}</option>
{{end}} {{end}}
</select> </select>
</div> </div>
@ -37,15 +37,15 @@
<div id="comment-area"> <div id="comment-area">
{{range .Step}} {{range .Step}}
<div class="comment first last"> <div class="comment first last">
<a class="comment-link" href="/doc/codewalk/?fileprint=/{{.File|urlquery_esc}}&lo={{.Lo|html_esc}}&hi={{.Hi|html_esc}}#mark" target="code-display"></a> <a class="comment-link" href="/doc/codewalk/?fileprint=/{{url .File}}&lo={{url .Lo}}&hi={{url .Hi}}#mark" target="code-display"></a>
<div class="comment-title">{{.Title|html_esc}}</div> <div class="comment-title">{{html .Title}}</div>
<div class="comment-text"> <div class="comment-text">
{{with .Err}} {{with .Err}}
ERROR LOADING FILE: {{.|html_esc}}<br/><br/> ERROR LOADING FILE: {{html .}}<br/><br/>
{{end}} {{end}}
{{.XML}} {{.XML}}
</div> </div>
<div class="comment-text file-name"><span class="path-file">{{.|html_esc}}</span></div> <div class="comment-text file-name"><span class="path-file">{{html .}}</span></div>
</div> </div>
{{end}} {{end}}
</div> </div>

View File

@ -7,9 +7,9 @@
<table class="layout"> <table class="layout">
{{range .}} {{range .}}
<tr> <tr>
<td><a href="{{.Name|html_esc}}">{{.Name|html_esc}}</a></td> <td><a href="{{url .Name}}">{{html .Name}}</a></td>
<td width="25">&nbsp;</td> <td width="25">&nbsp;</td>
<td>{{.Title|html_esc}}</td> <td>{{html .Title}}</td>
</tr> </tr>
{{end}} {{end}}
</table> </table>

View File

@ -18,11 +18,11 @@
</tr> </tr>
{{range .}} {{range .}}
<tr> <tr>
<td align="left"><a href="{{.|fileInfoName}}">{{.|fileInfoName}}</a></td> <td align="left"><a href="{{.|fileInfoName|url}}">{{.|fileInfoName|html}}</a></td>
<td></td> <td></td>
<td align="right">{{.|fileInfoSize}}</td> <td align="right">{{html .Size}}</td>
<td></td> <td></td>
<td align="left">{{.|fileInfoTime}}</td> <td align="left">{{.|fileInfoTime|html}}</td>
</tr> </tr>
{{end}} {{end}}

View File

@ -5,5 +5,5 @@
--> -->
<p> <p>
<span class="alert" style="font-size:120%">{{.|html_esc}}</span> <span class="alert" style="font-size:120%">{{html .}}</span>
</p> </p>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
{{with .Title}} {{with .Title}}
<title>{{.|html_esc}} - The Go Programming Language</title> <title>{{html .}} - The Go Programming Language</title>
{{else}} {{else}}
<title>The Go Programming Language</title> <title>The Go Programming Language</title>
{{end}} {{end}}
@ -25,7 +25,7 @@
<form method="GET" action="/search"> <form method="GET" action="/search">
{{with .PkgRoots}} {{with .PkgRoots}}
{{range .PkgRoots}} {{range .PkgRoots}}
<a href="/pkg/{{.|html_esc}}">{{.|html_esc}}</a> <span class="sep">|</span> <a href="/pkg/{{html .}}">{{html .}}</a> <span class="sep">|</span>
{{end}} {{end}}
{{else}} {{else}}
References: References:
@ -34,7 +34,7 @@
<a href="/cmd/">Commands</a> <span class="sep">|</span> <a href="/cmd/">Commands</a> <span class="sep">|</span>
<a href="/doc/go_spec.html">Specification</a> <a href="/doc/go_spec.html">Specification</a>
{{if .SearchBox}} {{if .SearchBox}}
<input id="search" type="search" name="q" value="{{if .Query}}{{.Query|html_esc}}{{end}}" class="{{if .Query}}{{else}}inactive{{end}}" placeholder="code search" results="0" /> <input id="search" type="search" name="q" value="{{with .Query}}{{html .}}{{end}}" class="{{if not .Query}}inactive{{end}}" placeholder="code search" results="0" />
{{end}} {{end}}
</form> </form>
</div> </div>
@ -50,10 +50,10 @@
{{end}} {{end}}
{{with .Title}} {{with .Title}}
<h1 id="generatedHeader">{{.|html_esc}}</h1> <h1 id="generatedHeader">{{html .}}</h1>
{{end}} {{end}}
{{with .Subtitle}} {{with .Subtitle}}
<span class="subtitle">{{.|html_esc}}</span> <span class="subtitle">{{html .}}</span>
{{end}} {{end}}
<!-- The Table of Contents is automatically inserted in this <div>. <!-- The Table of Contents is automatically inserted in this <div>.
@ -64,7 +64,7 @@
{{printf "%s" .Content}} {{printf "%s" .Content}}
</div> </div>
<div id="site-info"> <div id="site-info">
<p>Build version {{.Version|html_esc}}. Except as noted, this content is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.</p> <p>Build version {{html .Version}}. Except as noted, this content is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.</p>
</div> </div>
</div> </div>
</body> </body>

View File

@ -3,26 +3,22 @@
Use of this source code is governed by a BSD-style Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. license that can be found in the LICENSE file.
--> -->
{{$FSet := .FSet}}
{{$Info := .}}
{{with .PAst}} {{with .PAst}}
<pre>{{html_esc . $FSet}}</pre> <pre>{{html_node . $.FSet}}</pre>
{{end}} {{end}}
{{with .PDoc}} {{with .PDoc}}
<!-- PackageName is printed as title by the top-level template --> <!-- PackageName is printed as title by the top-level template -->
{{if $Info.IsPkg}} {{if $.IsPkg}}
{{/* ImportPath is a string - no need for FSet */}} <p><code>import "{{html .ImportPath}}"</code></p>
<p><code>import "{{.ImportPath|html_esc}}"</code></p>
{{end}} {{end}}
{{.Doc|html_comment}} {{html_comment .Doc}}
{{if $Info.IsPkg}} {{if $.IsPkg}}
{{with .Filenames}} {{with .Filenames}}
{{/* Filenames are strings - no need for FSet */}}
<p> <p>
<h4>Package files</h4> <h4>Package files</h4>
<span style="font-size:90%"> <span style="font-size:90%">
{{range .}} {{range .}}
<a href="/{{.|url_src}}">{{.|localname}}</a> <a href="/{{url_src .}}">{{.|localname|html}}</a>
{{end}} {{end}}
</span> </span>
</p> </p>
@ -32,53 +28,57 @@
<h2 id="Constants">Constants</h2> <h2 id="Constants">Constants</h2>
{{range .}} {{range .}}
{{html_comment .Doc}} {{html_comment .Doc}}
<pre>{{html_esc .Decl $FSet}}</pre> <pre>{{html_node .Decl $.FSet}}</pre>
{{end}} {{end}}
{{end}} {{end}}
{{with .Vars}} {{with .Vars}}
<h2 id="Variables">Variables</h2> <h2 id="Variables">Variables</h2>
{{range .}} {{range .}}
{{html_comment .Doc}} {{html_comment .Doc}}
<pre>{{html_esc .Decl $FSet}}</pre> <pre>{{html_node .Decl $.FSet}}</pre>
{{end}} {{end}}
{{end}} {{end}}
{{with .Funcs}} {{with .Funcs}}
{{range .}} {{range .}}
{{/* Name is a string - no need for FSet */}} {{/* Name is a string - no need for FSet */}}
<h2 id="{{.Name|html_esc}}">func <a href="/{{url_pos .Decl $FSet}}">{{.Name|html_esc}}</a></h2> {{$name := html .Name}}
<p><code>{{html_esc .Decl $FSet}}</code></p> <h2 id="{{$name}}">func <a href="/{{url_pos .Decl $.FSet}}">{{$name}}</a></h2>
{{.Doc|html_comment}} <p><code>{{html_node .Decl $.FSet}}</code></p>
{{html_comment .Doc}}
{{end}} {{end}}
{{end}} {{end}}
{{with .Types}} {{with .Types}}
{{range $type := .}} {{range .}}
<h2 id="{{html_esc .Type.Name $FSet}}">type <a href="/{{url_pos .Decl $FSet}}">{{html_esc .Type.Name $FSet}}</a></h2> {{$tname := html_node .Type.Name $.FSet}}
{{.Doc|html_comment}} <h2 id="{{$tname}}">type <a href="/{{url_pos .Decl $.FSet}}">{{$tname}}</a></h2>
<p><pre>{{html_esc .Decl $FSet}}</pre></p> {{html_comment .Doc}}
<p><pre>{{html_node .Decl $.FSet}}</pre></p>
{{range .Consts}} {{range .Consts}}
{{.Doc|html_comment}} {{html_comment .Doc}}
<pre>{{html_esc .Decl $FSet}}</pre> <pre>{{html_node .Decl $.FSet}}</pre>
{{end}} {{end}}
{{range .Vars}} {{range .Vars}}
{{.Doc|html_comment}} {{html_comment .Doc}}
<pre>{{html_esc .Decl $FSet}}</pre> <pre>{{html_node .Decl $.FSet}}</pre>
{{end}} {{end}}
{{range .Factories}} {{range .Factories}}
<h3 id="{{html_esc $type.Type.Name $FSet}}.{{.Name|html_esc}}">func <a href="/{{url_pos .Decl $FSet}}">{{.Name|html_esc}}</a></h3> {{$name := html .Name}}
<p><code>{{html_esc .Decl $FSet}}</code></p> <h3 id="{{$tname}}.{{$name}}">func <a href="/{{url_pos .Decl $.FSet}}">{{$name}}</a></h3>
{{.Doc|html_comment}} <p><code>{{html_node .Decl $.FSet}}</code></p>
{{html_comment .Doc}}
{{end}} {{end}}
{{range .Methods}} {{range .Methods}}
<h3 id="{{html_esc $type.Type.Name $FSet}}.{{.Name|html_esc}}">func ({{html_esc .Recv $FSet}}) <a href="/{{url_pos .Decl $FSet}}">{{.Name|html_esc}}</a></h3> {{$name := html .Name}}
<p><code>{{html_esc .Decl $FSet}}</code></p> <h3 id="{{$tname}}.{{$name}}">func ({{html_node .Recv $.FSet}}) <a href="/{{url_pos .Decl $.FSet}}">{{$name}}</a></h3>
{{.Doc|html_comment}} <p><code>{{html_node .Decl $.FSet}}</code></p>
{{html_comment .Doc}}
{{end}} {{end}}
{{end}} {{end}}
{{end}} {{end}}
{{with .Bugs}} {{with .Bugs}}
<h2 id="Bugs">Bugs</h2> <h2 id="Bugs">Bugs</h2>
{{range .}} {{range .}}
{{.|html_comment}} {{html_comment .}}
{{end}} {{end}}
{{end}} {{end}}
{{end}} {{end}}
@ -87,7 +87,7 @@
<p> <p>
{{/* PList entries are strings - no need for FSet */}} {{/* PList entries are strings - no need for FSet */}}
{{range .}} {{range .}}
<a href="?p={{html .}}">{{html .}}</a><br /> <a href="?p={{url .}}">{{html .}}</a><br />
{{end}} {{end}}
</p> </p>
{{end}} {{end}}
@ -102,7 +102,7 @@
<p> <p>
<table class="layout"> <table class="layout">
<tr> <tr>
<th align="left" colspan="{{.MaxHeight|html_esc}}">Name</th> <th align="left" colspan="{{html .MaxHeight}}">Name</th>
<td width="25">&nbsp;</td> <td width="25">&nbsp;</td>
<th align="left">Synopsis</th> <th align="left">Synopsis</th>
</tr> </tr>
@ -111,7 +111,7 @@
</tr> </tr>
{{range .List}} {{range .List}}
<tr> <tr>
{{.Depth|padding}} {{repeat `<td width="25"></td>` .Depth}}
<td align="left" colspan="{{html .Height}}"><a href="{{html .Path}}">{{html .Name}}</a></td> <td align="left" colspan="{{html .Height}}"><a href="{{html .Path}}">{{html .Name}}</a></td>
<td></td> <td></td>
<td align="left">{{html .Synopsis}}</td> <td align="left">{{html .Synopsis}}</td>

View File

@ -2,7 +2,7 @@
--------------------------------------- ---------------------------------------
*/}}{{with .PAst}}{{text . $FSet}}{{end}}{{/* */}}{{with .PAst}}{{text_node . $FSet}}{{end}}{{/*
--------------------------------------- ---------------------------------------
@ -16,7 +16,7 @@ import "{{.ImportPath}}"
--------------------------------------- ---------------------------------------
*/}}{{with .Doc}}{{text . $FSet}} */}}{{with .Doc}}{{text_node . $FSet}}
{{end}}{{/* {{end}}{{/*
--------------------------------------- ---------------------------------------
@ -24,7 +24,7 @@ import "{{.ImportPath}}"
*/}}{{with .Consts}} */}}{{with .Consts}}
CONSTANTS CONSTANTS
{{range .}}{{text .Decl $FSet}} {{range .}}{{text_node .Decl $FSet}}
{{.Doc}}{{end}} {{.Doc}}{{end}}
{{end}}{{/* {{end}}{{/*
@ -33,7 +33,7 @@ CONSTANTS
*/}}{{with .Vars}} */}}{{with .Vars}}
VARIABLES VARIABLES
{{range .}}{{text .Decl $FSet}} {{range .}}{{text_node .Decl $FSet}}
{{.Doc}}{{end}} {{.Doc}}{{end}}
{{end}}{{/* {{end}}{{/*
@ -42,7 +42,7 @@ VARIABLES
*/}}{{with .Funcs}} */}}{{with .Funcs}}
FUNCTIONS FUNCTIONS
{{range .}}{{text .Decl $FSet}} {{range .}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{end}}{{end}}{{/* {{end}}{{end}}{{/*
@ -51,15 +51,15 @@ FUNCTIONS
*/}}{{with .Types}} */}}{{with .Types}}
TYPES TYPES
{{range .}}{{text .Decl $FSet}} {{range .}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{range .Consts}}{{text .Decl $FSet}} {{range .Consts}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{end}}{{range .Vars}}{{text .Decl $FSet}} {{end}}{{range .Vars}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{end}}{{range .Factories}}{{text .Decl $FSet}} {{end}}{{range .Factories}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{end}}{{range .Methods}}{{text .Decl $FSet}} {{end}}{{range .Methods}}{{text_node .Decl $FSet}}
{{.Doc}} {{.Doc}}
{{end}}{{end}}{{end}}{{/* {{end}}{{end}}{{end}}{{/*

View File

@ -13,7 +13,7 @@
<p> <p>
<span class="alert" style="font-size:120%">Did you mean: </span> <span class="alert" style="font-size:120%">Did you mean: </span>
{{range .Alts}} {{range .Alts}}
<a href="search?q={{.|urlquery_esc}}" style="font-size:120%">{{.|html_esc}}</a> <a href="search?q={{url .}}" style="font-size:120%">{{html .}}</a>
{{end}} {{end}}
</p> </p>
{{end}} {{end}}
@ -21,12 +21,13 @@
{{with .Decls}} {{with .Decls}}
<h2 id="Global">Package-level declarations</h2> <h2 id="Global">Package-level declarations</h2>
{{range .}} {{range .}}
<h3 id="Global_{{.Pak.Path|url_pkg}}">package <a href="/{{.Pak.Path|url_pkg}}">{{.Pak.Name|html_esc}}</a></h3> <h3 id="Global_{{url_pkg .Pak.Path}}">package <a href="/{{url_pkg .Pak.Path}}">{{html .Pak.Name}}</a></h3>
{{range $File := .Files}} {{range .Files}}
{{$path := url_src .File.Path}}
{{range .Groups}} {{range .Groups}}
{{range .Infos}} {{range .Infos}}
<a href="/{{$File.File.Path|url_src}}?h={{$SearchResult.Query|urlquery_esc}}#L{{.|infoLine}}">{{$File.File.Path|url_src}}:{{.|infoLine}}</a> <a href="/{{$path}}?h={{url $SearchResult.Query}}#L{{infoLine .}}">{{$path}}:{{infoLine .}}</a>
{{.|infoSnippet}} {{infoSnippet .}}
{{end}} {{end}}
{{end}} {{end}}
{{end}} {{end}}
@ -35,18 +36,19 @@
{{with .Others}} {{with .Others}}
<h2 id="Local">Local declarations and uses</h2> <h2 id="Local">Local declarations and uses</h2>
{{range .}} {{range .}}
<h3 id="Local_{{.Pak.Path|url_pkg}}">package <a href="/{{.Pak.Path|url_pkg}}">{{.Pak.Name|html_esc}}</a></h3> <h3 id="Local_{{url_pkg .Pak.Path}}">package <a href="/{{url_pkg .Pak.Path}}">{{html .Pak.Name}}</a></h3>
{{range $File := .Files}} {{range .Files}}
<a href="/{{.File.Path|url_src}}?h={{$SearchResult.Query|urlquery_esc}}">{{.File.Path|url_src}}</a> {{$path := url_src .File.Path}}
<a href="/{{$path}}?h={{url $SearchResult.Query}}">{{$path}}</a>
<table class="layout"> <table class="layout">
{{range .Groups}} {{range .Groups}}
<tr> <tr>
<td width="25"></td> <td width="25"></td>
<th align="left" valign="top">{{.Kind|infoKind}}</th> <th align="left" valign="top">{{infoKind .Kind}}</th>
<td align="left" width="4"></td> <td align="left" width="4"></td>
<td> <td>
{{range .Infos}} {{range .Infos}}
<a href="/{{$File.File.Path|url_src}}?h={{$SearchResult.Query|urlquery_esc}}#L{{.|infoLine}}">{{.|infoLine}}</a> <a href="/{{$path}}?h={{url $SearchResult.Query}}#L{{infoLine .}}">{{infoLine .}}</a>
{{end}} {{end}}
</td> </td>
</tr> </tr>
@ -58,26 +60,27 @@
{{end}} {{end}}
{{with .Textual}} {{with .Textual}}
{{if $SearchResult.Complete}} {{if $SearchResult.Complete}}
<h2 id="Textual">{{$SearchResult.Found|html_esc}} textual occurrences</h2> <h2 id="Textual">{{html $SearchResult.Found}} textual occurrences</h2>
{{else}} {{else}}
<h2 id="Textual">More than {{$SearchResult.Found|html_esc}} textual occurrences</h2> <h2 id="Textual">More than {{html $SearchResult.Found}} textual occurrences</h2>
<p> <p>
<span class="alert" style="font-size:120%">Not all files or lines containing "{{$SearchResult.Query|html_esc}}" are shown.</span> <span class="alert" style="font-size:120%">Not all files or lines containing "{{html $SearchResult.Query}}" are shown.</span>
</p> </p>
{{end}} {{end}}
<p> <p>
<table class="layout"> <table class="layout">
{{range $File := .}} {{range .}}
{{$path := url_src .Filename}}
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<a href="/{{.Filename|url_src}}?h={{$SearchResult.Query|urlquery_esc}}">{{.Filename|url_src}}</a>: <a href="/{{$path}}?h={{url $SearchResult.Query}}">{{$path}}</a>:
</td> </td>
<td align="left" width="4"></td> <td align="left" width="4"></td>
<th align="left" valign="top">{{.Lines|numlines}}</th> <th align="left" valign="top">{{len .Lines}}</th>
<td align="left" width="4"></td> <td align="left" width="4"></td>
<td align="left"> <td align="left">
{{range .Lines}} {{range .Lines}}
<a href="/{{$File.Filename|url_src}}?h={{$SearchResult.Query|urlquery_esc}}#L{{.|html_esc}}">{{.|html_esc}}</a> <a href="/{{$path}}?h={{url $SearchResult.Query}}#L{{url .}}">{{html .}}</a>
{{end}} {{end}}
{{if not $SearchResult.Complete}} {{if not $SearchResult.Complete}}
... ...

View File

@ -17,8 +17,9 @@ DID YOU MEAN
PACKAGE-LEVEL DECLARATIONS PACKAGE-LEVEL DECLARATIONS
{{range .}}package {{.Pak.Name}} {{range .}}package {{.Pak.Name}}
{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{$File.File.Path|url_src}}:{{.|infoLine}}{{end}} {{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{url_src $File.File.Path}}:{{infoLine .}}{{end}}
{{end}}{{end}}{{/* .Files */}}{{end}}{{end}}{{/* .Decls */}}{{/* {{end}}{{end}}{{/* .Files */}}
{{end}}{{end}}{{/* .Decls */}}{{/*
--------------------------------------- ---------------------------------------
@ -26,7 +27,7 @@ PACKAGE-LEVEL DECLARATIONS
LOCAL DECLARATIONS AND USES LOCAL DECLARATIONS AND USES
{{range .}}package {{.Pak.Name}} {{range .}}package {{.Pak.Name}}
{{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{$File.File.Path|url_src}}:{{.|infoLine}} {{range $File := .Files}}{{range .Groups}}{{range .Infos}} {{url_src $File.File.Path}}:{{infoLine .}}
{{end}}{{end}}{{end}}{{/* .Files */}} {{end}}{{end}}{{end}}{{/* .Files */}}
{{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/* {{end}}{{end}}{{/* .Others */}}{{end}}{{/* .Hit */}}{{/*
@ -34,6 +35,6 @@ LOCAL DECLARATIONS AND USES
*/}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}} */}}{{if .Textual}}{{if .Complete}}{{.Found}} TEXTUAL OCCURRENCES{{else}}MORE THAN {{.Found}} TEXTUAL OCCURRENCES{{end}}
{{range .Textual}}{{.Lines|numlines}} {{.Filename|url_src}} {{range .Textual}}{{len .Lines}} {{url_src .Filename}}
{{end}}{{if not .Complete}}... ... {{end}}{{if not .Complete}}... ...
{{end}}{{end}} {{end}}{{end}}

View File

@ -371,38 +371,6 @@ func writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
(&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x) (&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)
} }
// Write anything to w.
func writeAny(w io.Writer, fset *token.FileSet, x interface{}) {
switch v := x.(type) {
case []byte:
w.Write(v)
case string:
w.Write([]byte(v))
case ast.Decl, ast.Expr, ast.Stmt, *ast.File:
writeNode(w, fset, x)
default:
fmt.Fprint(w, x)
}
}
// Write anything html-escaped to w.
func writeAnyHTML(w io.Writer, fset *token.FileSet, x interface{}) {
switch v := x.(type) {
case []byte:
template.HTMLEscape(w, v)
case string:
template.HTMLEscape(w, []byte(v))
case ast.Decl, ast.Expr, ast.Stmt, *ast.File:
var buf bytes.Buffer
writeNode(&buf, fset, x)
FormatText(w, buf.Bytes(), -1, true, "", nil)
default:
var buf bytes.Buffer
fmt.Fprint(&buf, x)
template.HTMLEscape(w, buf.Bytes())
}
}
func fileset(x []interface{}) *token.FileSet { func fileset(x []interface{}) *token.FileSet {
if len(x) > 1 { if len(x) > 1 {
if fset, ok := x[1].(*token.FileSet); ok { if fset, ok := x[1].(*token.FileSet); ok {
@ -412,32 +380,6 @@ func fileset(x []interface{}) *token.FileSet {
return nil return nil
} }
// Template formatter for "html-esc" format.
func htmlEscFmt(w io.Writer, format string, x ...interface{}) {
writeAnyHTML(w, fileset(x), x[0])
}
// Template formatter for "html-comment" format.
func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {
var buf bytes.Buffer
writeAny(&buf, fileset(x), x[0])
// TODO(gri) Provide list of words (e.g. function parameters)
// to be emphasized by ToHTML.
doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping
}
// Template formatter for "" (default) format.
func textFmt(w io.Writer, format string, x ...interface{}) {
writeAny(w, fileset(x), x[0])
}
// Template formatter for "urlquery-esc" format.
func urlQueryEscFmt(w io.Writer, format string, x ...interface{}) {
var buf bytes.Buffer
writeAny(&buf, fileset(x), x[0])
template.HTMLEscape(w, []byte(http.URLEscape(string(buf.Bytes()))))
}
// Template formatter for the various "url-xxx" formats excluding url-esc. // Template formatter for the various "url-xxx" formats excluding url-esc.
func urlFmt(w io.Writer, format string, x ...interface{}) { func urlFmt(w io.Writer, format string, x ...interface{}) {
var path string var path string
@ -559,56 +501,17 @@ func infoSnippetFmt(w io.Writer, format string, x ...interface{}) {
w.Write(text) w.Write(text)
} }
// Template formatter for "padding" format.
func paddingFmt(w io.Writer, format string, x ...interface{}) {
for i := x[0].(int); i > 0; i-- {
fmt.Fprint(w, `<td width="25"></td>`)
}
}
// Template formatter for "localname" format.
func localnameFmt(w io.Writer, format string, x ...interface{}) {
_, localname := filepath.Split(x[0].(string))
template.HTMLEscape(w, []byte(localname))
}
// Template formatter for "fileInfoName" format.
func fileInfoNameFmt(w io.Writer, format string, x ...interface{}) {
fi := x[0].(FileInfo)
template.HTMLEscape(w, []byte(fi.Name()))
if fi.IsDirectory() {
w.Write([]byte{'/'})
}
}
// Template formatter for "fileInfoSize" format.
func fileInfoSizeFmt(w io.Writer, format string, x ...interface{}) {
fmt.Fprintf(w, "%d", x[0].(FileInfo).Size())
}
// Template formatter for "fileInfoTime" format.
func fileInfoTimeFmt(w io.Writer, format string, x ...interface{}) {
if t := x[0].(FileInfo).Mtime_ns(); t != 0 {
template.HTMLEscape(w, []byte(time.SecondsToLocalTime(t/1e9).String()))
}
// don't print epoch if time is obviously not set
}
// Template formatter for "numlines" format.
func numlinesFmt(w io.Writer, format string, x ...interface{}) {
list := x[0].([]int)
fmt.Fprintf(w, "%d", len(list))
}
// TODO(gri): Remove this type once fmtMap2funcMap is gone. // TODO(gri): Remove this type once fmtMap2funcMap is gone.
type FormatterMap map[string]func(io.Writer, string, ...interface{}) type FormatterMap map[string]func(io.Writer, string, ...interface{})
// TODO(gri): Remove the need for this conversion function by rewriting // TODO(gri): Remove the need for this conversion function by rewriting
// the old template formatters into new template functions. // the old template formatters into new template functions.
func fmtMap2funcMap(fmtMap FormatterMap) template.FuncMap { func append2funcMap(funcMap template.FuncMap, fmtMap FormatterMap) template.FuncMap {
funcMap := make(template.FuncMap)
for n, f := range fmtMap { for n, f := range fmtMap {
name, fmt := n, f // separate instance of name, fmt for each closure! 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 { funcMap[name] = func(args ...interface{}) string {
var buf bytes.Buffer var buf bytes.Buffer
fmt(&buf, name, args...) fmt(&buf, name, args...)
@ -618,23 +521,63 @@ func fmtMap2funcMap(fmtMap FormatterMap) template.FuncMap {
return funcMap return funcMap
} }
var fmap = fmtMap2funcMap(FormatterMap{ func textNodeFunc(node interface{}, fset *token.FileSet) string {
"text": textFmt, var buf bytes.Buffer
"html_esc": htmlEscFmt, writeNode(&buf, fset, node)
"html_comment": htmlCommentFmt, return buf.String()
"urlquery_esc": urlQueryEscFmt, }
"url_pkg": urlFmt,
"url_src": urlFmt, func htmlNodeFunc(node interface{}, fset *token.FileSet) string {
"url_pos": urlFmt, var buf1 bytes.Buffer
"infoKind": infoKindFmt, writeNode(&buf1, fset, node)
"infoLine": infoLineFmt, var buf2 bytes.Buffer
"infoSnippet": infoSnippetFmt, FormatText(&buf2, buf1.Bytes(), -1, true, "", nil)
"padding": paddingFmt, return buf2.String()
"fileInfoName": fileInfoNameFmt, }
"fileInfoSize": fileInfoSizeFmt,
"fileInfoTime": fileInfoTimeFmt, func htmlCommentFunc(comment string) string {
"localname": localnameFmt, var buf bytes.Buffer
"numlines": numlinesFmt, // 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 fileInfoNameFunc(fi FileInfo) string {
name := fi.Name()
if fi.IsDirectory() {
name += "/"
}
return name
}
func fileInfoTimeFunc(fi FileInfo) string {
if t := fi.Mtime_ns(); t != 0 {
return time.SecondsToLocalTime(t / 1e9).String()
}
return "" // don't return epoch if time is obviously not set
}
func localnameFunc(path string) string {
_, localname := filepath.Split(path)
return localname
}
var fmap = append2funcMap(template.FuncMap{
"text_node": textNodeFunc,
"html_node": htmlNodeFunc,
"html_comment": htmlCommentFunc,
"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,
}) })
func readTemplate(name string) *template.Template { func readTemplate(name string) *template.Template {

View File

@ -401,9 +401,11 @@ func main() {
fmt.Println() fmt.Println()
} }
if *html { if *html {
writeAnyHTML(os.Stdout, info.FSet, d) var buf bytes.Buffer
writeNode(&buf, info.FSet, d)
FormatText(os.Stdout, buf.Bytes(), -1, true, "", nil)
} else { } else {
writeAny(os.Stdout, info.FSet, d) writeNode(os.Stdout, info.FSet, d)
} }
fmt.Println() fmt.Println()
} }