summaryrefslogtreecommitdiff
path: root/src/cmd/godoc/godoc.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/godoc/godoc.go')
-rw-r--r--src/cmd/godoc/godoc.go104
1 files changed, 57 insertions, 47 deletions
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 6a00a3e70..c91dc33db 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -274,7 +274,7 @@ func relativePath(path string) string {
// ----------------------------------------------------------------------------
// Tab conversion
-var spaces = []byte(" ") // 16 spaces seems like a good number
+var spaces = []byte(" ") // 32 spaces seems like a good number
const (
indenting = iota
@@ -291,25 +291,31 @@ type tconv struct {
func (p *tconv) writeIndent() (err os.Error) {
i := p.indent
- for i > len(spaces) {
+ for i >= len(spaces) {
i -= len(spaces)
if _, err = p.output.Write(spaces); err != nil {
return
}
}
- _, err = p.output.Write(spaces[0:i])
+ // i < len(spaces)
+ if i > 0 {
+ _, err = p.output.Write(spaces[0:i])
+ }
return
}
func (p *tconv) Write(data []byte) (n int, err os.Error) {
+ if len(data) == 0 {
+ return
+ }
pos := 0 // valid if p.state == collecting
var b byte
for n, b = range data {
switch p.state {
case indenting:
switch b {
- case '\t', '\v':
+ case '\t':
p.indent += *tabwidth
case '\n':
p.indent = 0
@@ -336,7 +342,7 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) {
}
}
n = len(data)
- if p.state == collecting {
+ if pos < n && p.state == collecting {
_, err = p.output.Write(data[pos:])
}
return
@@ -346,47 +352,51 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) {
// ----------------------------------------------------------------------------
// Templates
-// Write an AST-node to w; optionally html-escaped.
-func writeNode(w io.Writer, fset *token.FileSet, node interface{}, html bool) {
- mode := printer.TabIndent | printer.UseSpaces
- if html {
- mode |= printer.GenHTML
- }
+// Write an AST node to w.
+func writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
// convert trailing tabs into spaces using a tconv filter
// to ensure a good outcome in most browsers (there may still
// be tabs in comments and strings, but converting those into
// the right number of spaces is much harder)
- (&printer.Config{mode, *tabwidth, nil}).Fprint(&tconv{output: w}, fset, node)
+ //
+ // TODO(gri) rethink printer flags - perhaps tconv can be eliminated
+ // with an another printer mode (which is more efficiently
+ // implemented in the printer than here with another layer)
+ mode := printer.TabIndent | printer.UseSpaces
+ (&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)
}
-// Write text to w; optionally html-escaped.
-func writeText(w io.Writer, text []byte, html bool) {
- if html {
- template.HTMLEscape(w, text)
- return
+// 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)
}
- w.Write(text)
}
-// Write anything to w; optionally html-escaped.
-func writeAny(w io.Writer, fset *token.FileSet, html bool, x interface{}) {
+// Write anything html-escaped to w.
+func writeAnyHTML(w io.Writer, fset *token.FileSet, x interface{}) {
switch v := x.(type) {
case []byte:
- writeText(w, v, html)
+ template.HTMLEscape(w, v)
case string:
- writeText(w, []byte(v), html)
+ template.HTMLEscape(w, []byte(v))
case ast.Decl, ast.Expr, ast.Stmt, *ast.File:
- writeNode(w, fset, x, html)
+ var buf bytes.Buffer
+ writeNode(&buf, fset, x)
+ FormatText(w, buf.Bytes(), -1, true, "", nil)
default:
- if html {
- var buf bytes.Buffer
- fmt.Fprint(&buf, x)
- writeText(w, buf.Bytes(), true)
- } else {
- fmt.Fprint(w, x)
- }
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, x)
+ template.HTMLEscape(w, buf.Bytes())
}
}
@@ -401,24 +411,16 @@ func fileset(x []interface{}) *token.FileSet {
}
-// Template formatter for "html" format.
-func htmlFmt(w io.Writer, format string, x ...interface{}) {
- writeAny(w, fileset(x), true, x[0])
-}
-
-
// Template formatter for "html-esc" format.
func htmlEscFmt(w io.Writer, format string, x ...interface{}) {
- var buf bytes.Buffer
- writeAny(&buf, fileset(x), false, x[0])
- template.HTMLEscape(w, buf.Bytes())
+ 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), false, x[0])
+ 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
@@ -427,14 +429,14 @@ func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {
// Template formatter for "" (default) format.
func textFmt(w io.Writer, format string, x ...interface{}) {
- writeAny(w, fileset(x), false, x[0])
+ 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), false, x[0])
+ writeAny(&buf, fileset(x), x[0])
template.HTMLEscape(w, []byte(http.URLEscape(string(buf.Bytes()))))
}
@@ -603,7 +605,6 @@ func numlinesFmt(w io.Writer, format string, x ...interface{}) {
var fmap = template.FormatterMap{
"": textFmt,
- "html": htmlFmt,
"html-esc": htmlEscFmt,
"html-comment": htmlCommentFmt,
"urlquery-esc": urlQueryEscFmt,
@@ -683,7 +684,7 @@ func servePage(w http.ResponseWriter, title, subtitle, query string, content []b
content,
}
- if err := godocHTML.Execute(&d, w); err != nil {
+ if err := godocHTML.Execute(w, &d); err != nil {
log.Printf("godocHTML.Execute: %s", err)
}
}
@@ -751,7 +752,7 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin
func applyTemplate(t *template.Template, name string, data interface{}) []byte {
var buf bytes.Buffer
- if err := t.Execute(data, &buf); err != nil {
+ if err := t.Execute(&buf, data); err != nil {
log.Printf("%s.Execute: %s", name, err)
}
return buf.Bytes()
@@ -775,8 +776,12 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
return
}
- contents := FormatText(src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
- servePage(w, title+" "+relpath, "", "", contents)
+ var buf bytes.Buffer
+ buf.WriteString("<pre>")
+ FormatText(&buf, src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
+ buf.WriteString("</pre>")
+
+ servePage(w, title+" "+relpath, "", "", buf.Bytes())
}
@@ -891,6 +896,11 @@ type PageInfo struct {
}
+func (info *PageInfo) IsEmpty() bool {
+ return info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil
+}
+
+
type httpHandler struct {
pattern string // url pattern; e.g. "/pkg/"
fsRoot string // file system root to which the pattern is mapped