Commit 1605176e authored by Russ Cox's avatar Russ Cox

godoc: use data-driven templates for html, text generation

R=gri
DELTA=1341  (668 added, 282 deleted, 391 changed)
OCL=27485
CL=27526
parent bafd1787
...@@ -7,7 +7,11 @@ ...@@ -7,7 +7,11 @@
// //
package ast package ast
import "token" import (
"token";
"unicode";
"utf8";
)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -45,7 +49,7 @@ type Expr interface { ...@@ -45,7 +49,7 @@ type Expr interface {
// visitor v invokes the node-specific DoX function of the visitor. // visitor v invokes the node-specific DoX function of the visitor.
// //
Visit(v ExprVisitor); Visit(v ExprVisitor);
// Pos returns the (beginning) position of the expression. // Pos returns the (beginning) position of the expression.
Pos() token.Position; Pos() token.Position;
} }
...@@ -57,7 +61,7 @@ type Stmt interface { ...@@ -57,7 +61,7 @@ type Stmt interface {
// visitor v invokes the node-specific DoX function of the visitor. // visitor v invokes the node-specific DoX function of the visitor.
// //
Visit(v StmtVisitor); Visit(v StmtVisitor);
// Pos returns the (beginning) position of the statement. // Pos returns the (beginning) position of the statement.
Pos() token.Position; Pos() token.Position;
} }
...@@ -69,7 +73,7 @@ type Decl interface { ...@@ -69,7 +73,7 @@ type Decl interface {
// visitor v invokes the node-specific DoX function of the visitor. // visitor v invokes the node-specific DoX function of the visitor.
// //
Visit(v DeclVisitor); Visit(v DeclVisitor);
// Pos returns the (beginning) position of the declaration. // Pos returns the (beginning) position of the declaration.
Pos() token.Position; Pos() token.Position;
} }
...@@ -419,6 +423,24 @@ func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); } ...@@ -419,6 +423,24 @@ func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); }
func (x *ChanType) Visit(v ExprVisitor) { v.DoChanType(x); } func (x *ChanType) Visit(v ExprVisitor) { v.DoChanType(x); }
// IsExported returns whether name is an exported Go symbol
// (i.e., whether it begins with an uppercase letter).
func IsExported(name string) bool {
ch, len := utf8.DecodeRuneInString(name, 0);
return unicode.IsUpper(ch);
}
// IsExported returns whether name is an exported Go symbol
// (i.e., whether it begins with an uppercase letter).
func (name *ast.Ident) IsExported() bool {
return IsExported(name.Value);
}
func (name *ast.Ident) String() string {
return name.Value;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
...@@ -688,7 +710,7 @@ type ( ...@@ -688,7 +710,7 @@ type (
// A declaration is represented by one of the following declaration nodes. // A declaration is represented by one of the following declaration nodes.
// //
type ( type (
// A BadDecl node is a placeholder for declarations containing // A BadDecl node is a placeholder for declarations containing
// syntax errors for which no correct declaration nodes can be // syntax errors for which no correct declaration nodes can be
// created. // created.
......
...@@ -56,6 +56,8 @@ GOMAXPROCS=10 make test ...@@ -56,6 +56,8 @@ GOMAXPROCS=10 make test
make clean make clean
time make time make
make smoketest make smoketest
# TODO: this belongs elsewhere
cp godoc $HOME/bin
) || exit $? ) || exit $?
(xcd ../doc/progs (xcd ../doc/progs
......
...@@ -30,7 +30,7 @@ install: pretty godoc untab ...@@ -30,7 +30,7 @@ install: pretty godoc untab
clean: clean:
rm -f pretty untab godoc *.6 *.a 6.out *~ rm -f pretty untab godoc *.6 *.a 6.out *~
godoc.6: docprinter.6 compilation.6 godoc.6: docprinter.6 compilation.6 comment.6
pretty.6: platform.6 astprinter.6 compilation.6 pretty.6: platform.6 astprinter.6 compilation.6
...@@ -44,5 +44,7 @@ astprinter.6: utils.6 symboltable.6 ...@@ -44,5 +44,7 @@ astprinter.6: utils.6 symboltable.6
docprinter.6: astprinter.6 docprinter.6: astprinter.6
comment.6:
%.6: %.go %.6: %.go
$(G) $(F) $< $(G) $(F) $<
// Copyright 2009 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.
// Godoc comment -> HTML formatting
package comment
import (
"fmt";
"io";
"template";
)
// Split bytes into lines.
func split(text []byte) [][]byte {
// count lines
n := 0;
last := 0;
for i, c := range text {
if c == '\n' {
last = i+1;
n++;
}
}
if last < len(text) {
n++;
}
// split
out := make([][]byte, n);
last = 0;
n = 0;
for i, c := range text {
if c == '\n' {
out[n] = text[last : i+1];
last = i+1;
n++;
}
}
if last < len(text) {
out[n] = text[last : len(text)];
}
return out;
}
var (
ldquo = io.StringBytes("&ldquo;");
rdquo = io.StringBytes("&rdquo;");
)
// Escape comment text for HTML.
// Also, turn `` into &ldquo; and '' into &rdquo;.
func commentEscape(w io.Write, s []byte) {
last := 0;
for i := 0; i < len(s)-1; i++ {
if s[i] == s[i+1] && (s[i] == '`' || s[i] == '\'') {
template.HtmlEscape(w, s[last : i]);
last = i+2;
switch s[i] {
case '`':
w.Write(ldquo);
case '\'':
w.Write(rdquo);
}
i++; // loop will add one more
}
}
template.HtmlEscape(w, s[last : len(s)]);
}
var (
html_p = io.StringBytes("<p>\n");
html_endp = io.StringBytes("</p>\n");
html_pre = io.StringBytes("<pre>");
html_endpre = io.StringBytes("</pre>\n");
)
func indentLen(s []byte) int {
i := 0;
for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
i++;
}
return i;
}
func isBlank(s []byte) bool {
return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}
func commonPrefix(a, b []byte) []byte {
i := 0;
for i < len(a) && i < len(b) && a[i] == b[i] {
i++;
}
return a[0 : i];
}
func unindent(block [][]byte) {
if len(block) == 0 {
return;
}
// compute maximum common white prefix
prefix := block[0][0 : indentLen(block[0])];
for i, line := range block {
if !isBlank(line) {
prefix = commonPrefix(prefix, line[0 : indentLen(line)]);
}
}
n := len(prefix);
// remove
for i, line := range block {
if !isBlank(line) {
block[i] = line[n : len(line)];
}
}
}
// Convert comment text to formatted HTML.
// The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
// Turn each run of multiple \n into </p><p>
// Turn each run of indented lines into <pre> without indent.
//
// TODO(rsc): I'd like to pass in an array of variable names []string
// and then italicize those strings when they appear as words.
func ToHtml(w io.Write, s []byte) {
inpara := false;
/* TODO(rsc): 6g cant generate code for these
close := func() {
if inpara {
w.Write(html_endp);
inpara = false;
}
};
open := func() {
if !inpara {
w.Write(html_p);
inpara = true;
}
};
*/
lines := split(s);
unindent(lines);
for i := 0; i < len(lines); {
line := lines[i];
if isBlank(line) {
// close paragraph
if inpara {
w.Write(html_endp);
inpara = false;
}
i++;
continue;
}
if indentLen(line) > 0 {
// close paragraph
if inpara {
w.Write(html_endp);
inpara = false;
}
// count indented or blank lines
j := i+1;
for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
j++;
}
// but not trailing blank lines
for j > i && isBlank(lines[j-1]) {
j--;
}
block := lines[i : j];
i = j;
unindent(block);
// put those lines in a pre block.
// they don't get the nice text formatting,
// just html escaping
w.Write(html_pre);
for k, line := range block {
template.HtmlEscape(w, line);
}
w.Write(html_endpre);
continue;
}
// open paragraph
if !inpara {
w.Write(html_p);
inpara = true;
}
commentEscape(w, lines[i]);
i++;
}
if inpara {
w.Write(html_endp);
inpara = false;
}
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment