summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/gri/pretty/astprinter.go88
-rw-r--r--usr/gri/pretty/docprinter.go67
-rw-r--r--usr/gri/pretty/godoc.go369
-rw-r--r--usr/gri/pretty/pretty.go2
4 files changed, 301 insertions, 225 deletions
diff --git a/usr/gri/pretty/astprinter.go b/usr/gri/pretty/astprinter.go
index 66fc3616f..4e5fcba07 100644
--- a/usr/gri/pretty/astprinter.go
+++ b/usr/gri/pretty/astprinter.go
@@ -5,22 +5,20 @@
package astPrinter
import (
- "io";
- "vector";
- "tabwriter";
+ "ast";
"flag";
"fmt";
+ "io";
+ "os";
"strings";
- "utf8";
- "unicode";
-
- "utils";
+ "tabwriter";
"token";
- "ast";
- "template";
- "symboltable";
+ "unicode";
+ "utf8";
+ "vector";
)
+
var (
debug = flag.Bool("ast_debug", false, "print debugging information");
@@ -76,8 +74,47 @@ func hasExportedNames(names []*ast.Ident) bool {
// ----------------------------------------------------------------------------
+// TokenPrinter
+
+// TODO This is not yet used - should fix this.
+
+// An implementation of a TokenPrinter may be provided when
+// initializing an AST Printer. It is used to print tokens.
+//
+type TokenPrinter interface {
+ PrintLit(w io.Write, tok token.Token, value []byte);
+ PrintIdent(w io.Write, value string);
+ PrintToken(w io.Write, token token.Token);
+ PrintComment(w io.Write, value []byte);
+}
+
+
+type defaultPrinter struct {}
+
+func (p defaultPrinter) PrintLit(w io.Write, tok token.Token, value []byte) {
+ w.Write(value);
+}
+
+
+func (p defaultPrinter) PrintIdent(w io.Write, value string) {
+ fmt.Fprint(w, value);
+}
+
+
+func (p defaultPrinter) PrintToken(w io.Write, token token.Token) {
+ fmt.Fprint(w, token.String());
+}
+
+
+func (p defaultPrinter) PrintComment(w io.Write, value []byte) {
+ w.Write(value);
+}
+
+
+// ----------------------------------------------------------------------------
// ASTPrinter
+
// Separators - printed in a delayed fashion, depending on context.
const (
none = iota;
@@ -101,14 +138,17 @@ type Printer struct {
// output
text io.Write;
+ // token printing
+ tprinter TokenPrinter;
+
// formatting control
html bool;
full bool; // if false, print interface only; print all otherwise
// comments
comments []*ast.Comment; // the list of unassociated comments
- cindex int; // the current comment group index
- cpos token.Position; // the position of the next comment group
+ cindex int; // the current comment index
+ cpos token.Position; // the position of the next comment
// current state
lastpos token.Position; // position after last string
@@ -144,10 +184,17 @@ func (P *Printer) nextComments() {
}
-func (P *Printer) Init(text io.Write, comments []*ast.Comment, html bool) {
+func (P *Printer) Init(text io.Write, tprinter TokenPrinter, comments []*ast.Comment, html bool) {
// writers
P.text = text;
-
+
+ // token printing
+ if tprinter != nil {
+ P.tprinter = tprinter;
+ } else {
+ P.tprinter = defaultPrinter{};
+ }
+
// formatting control
P.html = html;
@@ -227,7 +274,7 @@ func (P *Printer) newline(n int) {
func (P *Printer) TaggedString(pos token.Position, tag, s, endtag string) {
// use estimate for pos if we don't have one
offs := pos.Offset;
- if offs == 0 {
+ if pos.Line == 0 {
offs = P.lastpos.Offset;
}
@@ -401,6 +448,17 @@ func (P *Printer) Error(pos token.Position, tok token.Token, msg string) {
}
+// An astPrinter implements io.Write.
+// TODO this is not yet used.
+func (P *Printer) Write(p []byte) (n int, err *os.Error) {
+ // TODO
+ // - no string conversion every time
+ // - return proper results
+ P.String(noPos, string(p));
+ return len(p), nil;
+}
+
+
// ----------------------------------------------------------------------------
// HTML support
diff --git a/usr/gri/pretty/docprinter.go b/usr/gri/pretty/docprinter.go
index 94fe50119..623c51614 100644
--- a/usr/gri/pretty/docprinter.go
+++ b/usr/gri/pretty/docprinter.go
@@ -136,25 +136,27 @@ func (doc *PackageDoc) addFunc(fun *ast.FuncDecl) {
typ.methods[name] = fdoc;
}
// if the type wasn't found, it wasn't exported
+ // TODO: a non-exported type may still have exported functions
+ // determine what to do in that case
+ return;
+ }
- } else {
- // perhaps a factory function
- // determine result type, if any
- if len(fun.Type.Results) >= 1 {
- res := fun.Type.Results[0];
- if len(res.Names) <= 1 {
- // exactly one (named or anonymous) result type
- typ = doc.lookupTypeDoc(res.Type);
- if typ != nil {
- typ.factories[name] = fdoc;
- return;
- }
+ // perhaps a factory function
+ // determine result type, if any
+ if len(fun.Type.Results) >= 1 {
+ res := fun.Type.Results[0];
+ if len(res.Names) <= 1 {
+ // exactly one (named or anonymous) result type
+ typ = doc.lookupTypeDoc(res.Type);
+ if typ != nil {
+ typ.factories[name] = fdoc;
+ return;
}
}
-
- // ordinary function
- doc.funcs[name] = fdoc;
}
+
+ // ordinary function
+ doc.funcs[name] = fdoc;
}
@@ -279,18 +281,6 @@ func untabify(s []byte) []byte {
}
-func stripWhiteSpace(s []byte) []byte {
- i, j := 0, len(s);
- for i < len(s) && s[i] <= ' ' {
- i++;
- }
- for j > i && s[j-1] <= ' ' {
- j--
- }
- return s[i : j];
-}
-
-
func stripCommentDelimiters(s []byte) []byte {
switch s[1] {
case '/': return s[2 : len(s)-1];
@@ -308,8 +298,25 @@ const /* formatting mode */ (
)
func printLine(p *astPrinter.Printer, line []byte, mode int) int {
- indented := len(line) > 0 && line[0] == '\t';
- line = stripWhiteSpace(line);
+ // If a line starts with " *" (as a result of a vertical /****/ comment),
+ // strip it away. For an example of such a comment, see src/lib/flag.go.
+ if len(line) >= 2 && line[0] == ' ' && line[1] == '*' {
+ line = line[2 : len(line)];
+ }
+
+ // The line is indented if it starts with a tab.
+ // In either case strip away a leading space or tab.
+ indented := false;
+ if len(line) > 0 {
+ switch line[0] {
+ case '\t':
+ indented = true;
+ fallthrough;
+ case ' ':
+ line = line[1 : len(line)];
+ }
+ }
+
if len(line) == 0 {
// empty line
switch mode {
@@ -426,7 +433,7 @@ func (t *typeDoc) print(p *astPrinter.Printer) {
func (doc *PackageDoc) Print(writer io.Write) {
var p astPrinter.Printer;
- p.Init(writer, nil, true);
+ p.Init(writer, nil, nil, true);
// program header
fmt.Fprintf(writer, "<h1>package %s</h1>\n", doc.name);
diff --git a/usr/gri/pretty/godoc.go b/usr/gri/pretty/godoc.go
index 8b428d38f..afedd7949 100644
--- a/usr/gri/pretty/godoc.go
+++ b/usr/gri/pretty/godoc.go
@@ -25,6 +25,7 @@ import (
"regexp";
"vector";
+ "astprinter";
"compilation"; // TODO removing this causes link errors - why?
"docprinter";
)
@@ -33,11 +34,12 @@ import (
// TODO
// - uniform use of path, filename, dirname, pakname, etc.
// - fix weirdness with double-/'s in paths
+// - cleanup uses of *root, GOROOT, etc. (quite a mess at the moment)
const (
docPrefix = "/doc/";
- srcPrefix = "/src/";
+ filePrefix = "/file/";
)
@@ -48,19 +50,16 @@ func getenv(varname string) string {
var (
- GOROOT string;
+ GOROOT = getenv("GOROOT");
// server control
verbose = flag.Bool("v", false, "verbose mode");
port = flag.String("port", "6060", "server port");
- root = flag.String("root", getenv("GOROOT"), "go root directory");
+ root = flag.String("root", GOROOT, "root directory");
// layout control
tabwidth = flag.Int("tabwidth", 4, "tab width");
usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks");
-
- // html template
- godoc_template = template.NewTemplateOrDie("godoc.html");
)
@@ -111,8 +110,13 @@ func isGoFile(dir *os.Dir) bool {
}
+func isHTMLFile(dir *os.Dir) bool {
+ return dir.IsRegular() && hasSuffix(dir.Name, ".html");
+}
+
+
func printLink(c *http.Conn, path, name string) {
- fmt.Fprintf(c, "<a href=\"%s\">%s</a><br />\n", srcPrefix + path + name, name);
+ fmt.Fprintf(c, "<a href=\"%s\">%s</a><br />\n", filePrefix + path + name, name);
}
@@ -189,6 +193,33 @@ func compile(path string, mode uint) (*ast.Program, errorList) {
// ----------------------------------------------------------------------------
+// Templates
+
+// html template
+// TODO initialize only if needed (i.e. if run as a server)
+var godoc_html = template.NewTemplateOrDie("godoc.html");
+
+func servePage(c *http.Conn, title string, contents func()) {
+ c.SetHeader("content-type", "text/html; charset=utf-8");
+
+ // TODO handle Apply errors
+ godoc_html.Apply(c, "<!--", template.Substitution {
+ "TITLE-->" : func() { fmt.Fprint(c, title); },
+ "HEADER-->" : func() { fmt.Fprint(c, title); },
+ "TIMESTAMP-->" : func() { fmt.Fprint(c, time.UTC().String()); },
+ "CONTENTS-->" : contents
+ });
+}
+
+
+func serveError(c *http.Conn, err, arg string) {
+ servePage(c, "Error", func () {
+ fmt.Fprintf(c, "%v (%s)\n", err, arg);
+ });
+}
+
+
+// ----------------------------------------------------------------------------
// Directories
type dirArray []os.Dir
@@ -214,45 +245,28 @@ func serveDir(c *http.Conn, dirname string) {
sort.Sort(dirArray(list));
- c.SetHeader("content-type", "text/html; charset=utf-8");
path := dirname + "/";
// Print contents in 3 sections: directories, go files, everything else
-
- // TODO handle Apply errors
- godoc_template.Apply(c, "<!--", template.Substitution {
- "TITLE-->" : func() {
- fmt.Fprint(c, dirname);
- },
-
- "HEADER-->" : func() {
- fmt.Fprint(c, dirname);
- },
-
- "TIMESTAMP-->" : func() {
- fmt.Fprint(c, time.UTC().String());
- },
-
- "CONTENTS-->" : func () {
- fmt.Fprintln(c, "<h2>Directories</h2>");
- for i, entry := range list {
- if entry.IsDirectory() {
- printLink(c, path, entry.Name);
- }
+ servePage(c, dirname + " - Contents", func () {
+ fmt.Fprintln(c, "<h2>Directories</h2>");
+ for i, entry := range list {
+ if entry.IsDirectory() {
+ printLink(c, path, entry.Name);
}
+ }
- fmt.Fprintln(c, "<h2>Go files</h2>");
- for i, entry := range list {
- if isGoFile(&entry) {
- printLink(c, path, entry.Name);
- }
+ fmt.Fprintln(c, "<h2>Go files</h2>");
+ for i, entry := range list {
+ if isGoFile(&entry) {
+ printLink(c, path, entry.Name);
}
+ }
- fmt.Fprintln(c, "<h2>Other files</h2>");
- for i, entry := range list {
- if !entry.IsDirectory() && !isGoFile(&entry) {
- fmt.Fprintf(c, "%s<br />\n", entry.Name);
- }
+ fmt.Fprintln(c, "<h2>Other files</h2>");
+ for i, entry := range list {
+ if !entry.IsDirectory() && !isGoFile(&entry) {
+ fmt.Fprintf(c, "%s<br />\n", entry.Name);
}
}
});
@@ -262,120 +276,96 @@ func serveDir(c *http.Conn, dirname string) {
// ----------------------------------------------------------------------------
// Files
-func printErrors(c *http.Conn, filename string, errors errorList) {
+func serveCompilationErrors(c *http.Conn, filename string, errors errorList) {
// open file
path := *root + filename;
fd, err1 := os.Open(path, os.O_RDONLY, 0);
defer fd.Close();
if err1 != nil {
- // TODO better error handling
- log.Stdoutf("%s: %v", path, err1);
+ serveError(c, err1.String(), path);
+ return;
}
// read source
var buf io.ByteBuffer;
n, err2 := io.Copy(fd, &buf);
if err2 != nil {
- // TODO better error handling
- log.Stdoutf("%s: %v", path, err2);
+ serveError(c, err2.String(), path);
+ return;
}
src := buf.Data();
// TODO handle Apply errors
- godoc_template.Apply(c, "<!--", template.Substitution {
- "TITLE-->" : func() {
- fmt.Fprint(c, filename);
- },
-
- "HEADER-->" : func() {
- fmt.Fprint(c, filename);
- },
-
- "TIMESTAMP-->" : func() {
- fmt.Fprint(c, time.UTC().String());
- },
-
- "CONTENTS-->" : func () {
- // section title
- fmt.Fprintf(c, "<h1>Compilation errors in %s</h1>\n", filename);
-
- // handle read errors
- if err1 != nil || err2 != nil /* 6g bug139 */ {
- fmt.Fprintf(c, "could not read file %s\n", filename);
- return;
- }
-
- // write source with error messages interspersed
- fmt.Fprintln(c, "<pre>");
- offs := 0;
- for i, e := range errors {
- if 0 <= e.pos.Offset && e.pos.Offset <= len(src) {
- // TODO handle Write errors
- c.Write(src[offs : e.pos.Offset]);
- // TODO this should be done using a .css file
- fmt.Fprintf(c, "<b><font color=red>%s >>></font></b>", e.msg);
- offs = e.pos.Offset;
- } else {
- log.Stdoutf("error position %d out of bounds (len = %d)", e.pos.Offset, len(src));
- }
+ servePage(c, filename, func () {
+ // section title
+ fmt.Fprintf(c, "<h1>Compilation errors in %s</h1>\n", filename);
+
+ // handle read errors
+ if err1 != nil || err2 != nil /* 6g bug139 */ {
+ fmt.Fprintf(c, "could not read file %s\n", filename);
+ return;
+ }
+
+ // write source with error messages interspersed
+ fmt.Fprintln(c, "<pre>");
+ offs := 0;
+ for i, e := range errors {
+ if 0 <= e.pos.Offset && e.pos.Offset <= len(src) {
+ // TODO handle Write errors
+ c.Write(src[offs : e.pos.Offset]);
+ // TODO this should be done using a .css file
+ fmt.Fprintf(c, "<b><font color=red>%s >>></font></b>", e.msg);
+ offs = e.pos.Offset;
+ } else {
+ log.Stdoutf("error position %d out of bounds (len = %d)", e.pos.Offset, len(src));
}
- // TODO handle Write errors
- c.Write(src[offs : len(src)]);
- fmt.Fprintln(c, "</pre>");
}
+ // TODO handle Write errors
+ c.Write(src[offs : len(src)]);
+ fmt.Fprintln(c, "</pre>");
});
}
-func serveGoFile(c *http.Conn, dirname string, filenames []string) {
- // compute documentation
- var doc docPrinter.PackageDoc;
- for i, filename := range filenames {
- path := *root + "/" + dirname + "/" + filename;
- prog, errors := compile(path, parser.ParseComments);
- if len(errors) > 0 {
- c.SetHeader("content-type", "text/html; charset=utf-8");
- printErrors(c, filename, errors);
- return;
- }
-
- if i == 0 {
- // first package - initialize docPrinter
- doc.Init(prog.Name.Value);
- }
- doc.AddProgram(prog);
+func serveGoSource(c *http.Conn, dirname string, filename string) {
+ path := dirname + "/" + filename;
+ prog, errors := compile(*root + "/" + path, parser.ParseComments);
+ if len(errors) > 0 {
+ serveCompilationErrors(c, filename, errors);
+ return;
}
- c.SetHeader("content-type", "text/html; charset=utf-8");
-
- godoc_template.Apply(c, "<!--", template.Substitution {
- "TITLE-->" : func() {
- fmt.Fprintf(c, "%s - Go package documentation", doc.PackageName());
- },
-
- "HEADER-->" : func() {
- fmt.Fprintf(c, "%s - Go package documentation", doc.PackageName());
- },
-
- "TIMESTAMP-->" : func() {
- fmt.Fprint(c, time.UTC().String());
- },
-
- "CONTENTS-->" : func () {
- // write documentation
- writer := makeTabwriter(c); // for nicely formatted output
- doc.Print(writer);
- writer.Flush(); // ignore errors
- }
+ servePage(c, path + " - Go source", func () {
+ fmt.Fprintln(c, "<pre>");
+ var p astPrinter.Printer;
+ writer := makeTabwriter(c); // for nicely formatted output
+ p.Init(writer, nil, nil, true);
+ p.DoProgram(prog);
+ writer.Flush(); // ignore errors
+ fmt.Fprintln(c, "</pre>");
});
}
-func serveSrc(c *http.Conn, path string) {
+func serveHTMLFile(c *http.Conn, filename string) {
+ src, err1 := os.Open(filename, os.O_RDONLY, 0);
+ defer src.Close();
+ if err1 != nil {
+ serveError(c, err1.String(), filename);
+ return
+ }
+ written, err2 := io.Copy(src, c);
+ if err2 != nil {
+ serveError(c, err2.String(), filename);
+ return
+ }
+}
+
+
+func serveFile(c *http.Conn, path string) {
dir, err := os.Stat(*root + path);
if err != nil {
- c.WriteHeader(http.StatusNotFound);
- fmt.Fprintf(c, "Error: %v (%s)\n", err, path);
+ serveError(c, err.String(), path);
return;
}
@@ -383,10 +373,11 @@ func serveSrc(c *http.Conn, path string) {
case dir.IsDirectory():
serveDir(c, path);
case isGoFile(dir):
- serveGoFile(c, "", []string{path});
+ serveGoSource(c, "", path);
+ case isHTMLFile(dir):
+ serveHTMLFile(c, *root + path);
default:
- c.WriteHeader(http.StatusNotFound);
- fmt.Fprintf(c, "Error: Not a directory or .go file (%s)\n", path);
+ serveError(c, "Not a directory or .go file", path);
}
}
@@ -407,13 +398,12 @@ func (p pakArray) Less(i, j int) bool { return p[i].pakname < p[j].pakname; }
func (p pakArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
-var (
- pakMap map[string]*pakDesc; // dirname/pakname -> package descriptor
- pakList pakArray; // sorted list of packages; in sync with pakMap
-)
+// The global list of packages (sorted)
+// TODO should be accessed under a lock
+var pakList pakArray;
-func addFile(dirname string, filename string) {
+func addFile(pmap map[string]*pakDesc, dirname string, filename string) {
if hasSuffix(filename, "_test.go") {
// ignore package tests
return;
@@ -431,11 +421,11 @@ func addFile(dirname string, filename string) {
pakname := dirname + "/" + prog.Name.Value;
// find package descriptor
- pakdesc, found := pakMap[pakname];
+ pakdesc, found := pmap[pakname];
if !found {
// add a new descriptor
pakdesc = &pakDesc{dirname, prog.Name.Value, make(map[string]bool)};
- pakMap[pakname] = pakdesc;
+ pmap[pakname] = pakdesc;
}
//fmt.Printf("pak = %s, file = %s\n", pakname, filename);
@@ -448,11 +438,9 @@ func addFile(dirname string, filename string) {
}
-func addDirectory(dirname string) {
+func addDirectory(pmap map[string]*pakDesc, dirname string) {
// TODO should properly check device and inode to see if we have
// traversed this directory already
- //fmt.Printf("traversing %s\n", dirname);
-
fd, err1 := os.Open(*root + dirname, os.O_RDONLY, 0);
if err1 != nil {
log.Stdoutf("%s: %v", *root + dirname, err1);
@@ -469,30 +457,33 @@ func addDirectory(dirname string) {
switch {
case entry.IsDirectory():
if entry.Name != "." && entry.Name != ".." {
- addDirectory(dirname + "/" + entry.Name);
+ addDirectory(pmap, dirname + "/" + entry.Name);
}
case isGoFile(&entry):
//fmt.Printf("found %s/%s\n", dirname, entry.Name);
- addFile(dirname, entry.Name);
+ addFile(pmap, dirname, entry.Name);
}
}
}
func makePackageMap() {
- // TODO shold do this under a lock, eventually
+ // TODO shold do this under a lock
// populate package map
- pakMap = make(map[string]*pakDesc);
- addDirectory("");
+ pmap := make(map[string]*pakDesc);
+ addDirectory(pmap, "");
// build sorted package list
- pakList = make([]*pakDesc, len(pakMap));
+ plist := make(pakArray, len(pmap));
i := 0;
- for tmp, pakdesc := range pakMap {
- pakList[i] = pakdesc;
+ for tmp, pakdesc := range pmap {
+ plist[i] = pakdesc;
i++;
}
- sort.Sort(pakList);
+ sort.Sort(plist);
+
+ // install package list (TODO should do this under a lock)
+ pakList = plist;
if *verbose {
log.Stdoutf("%d packages found under %s", i, *root);
@@ -500,40 +491,46 @@ func makePackageMap() {
}
-func serveGoPackage(c *http.Conn, p *pakDesc) {
+func servePackage(c *http.Conn, p *pakDesc) {
// make a filename list
- list := make([]string, len(p.filenames));
+ filenames := make([]string, len(p.filenames));
i := 0;
for filename, tmp := range p.filenames {
- list[i] = filename;
+ filenames[i] = filename;
i++;
}
- serveGoFile(c, p.dirname, list);
+ // compute documentation
+ var doc docPrinter.PackageDoc;
+ for i, filename := range filenames {
+ path := *root + "/" + p.dirname + "/" + filename;
+ prog, errors := compile(path, parser.ParseComments);
+ if len(errors) > 0 {
+ serveCompilationErrors(c, filename, errors);
+ return;
+ }
+
+ if i == 0 {
+ // first package - initialize docPrinter
+ doc.Init(prog.Name.Value);
+ }
+ doc.AddProgram(prog);
+ }
+
+ servePage(c, doc.PackageName() + " - Go package documentation", func () {
+ writer := makeTabwriter(c); // for nicely formatted output
+ doc.Print(writer);
+ writer.Flush(); // ignore errors
+ });
}
func servePackageList(c *http.Conn, list *vector.Vector) {
- godoc_template.Apply(c, "<!--", template.Substitution {
- "TITLE-->" : func() {
- fmt.Fprint(c, "Packages");
- },
-
- "HEADER-->" : func() {
- fmt.Fprint(c, "Packages");
- },
-
- "TIMESTAMP-->" : func() {
- fmt.Fprint(c, time.UTC().String());
- },
-
- "CONTENTS-->" : func () {
- // TODO should do this under a lock, eventually
- for i := 0; i < list.Len(); i++ {
- p := list.At(i).(*pakDesc);
- link := p.dirname + "/" + p.pakname;
- fmt.Fprintf(c, "<a href=\"%s\">%s</a> <font color=grey>(%s)</font><br />\n", docPrefix + link, p.pakname, link);
- }
+ servePage(c, "Packages", func () {
+ for i := 0; i < list.Len(); i++ {
+ p := list.At(i).(*pakDesc);
+ link := p.dirname + "/" + p.pakname;
+ fmt.Fprintf(c, "<a href=\"%s\">%s</a> <font color=grey>(%s)</font><br />\n", docPrefix + link, p.pakname, link);
}
});
}
@@ -543,8 +540,8 @@ func serveDoc(c *http.Conn, path string) {
// make regexp for package matching
rex, err := regexp.Compile(path);
if err != nil {
- // TODO report this via an error page
- log.Stdoutf("failed to compile regexp: %s", path);
+ serveError(c, err.String(), path);
+ return;
}
// build list of matching packages
@@ -555,9 +552,12 @@ func serveDoc(c *http.Conn, path string) {
}
}
- if list.Len() == 1 {
- serveGoPackage(c, list.At(0).(*pakDesc));
- } else {
+ switch list.Len() {
+ case 0:
+ serveError(c, "No packages found", path);
+ case 1:
+ servePackage(c, list.At(0).(*pakDesc));
+ default:
servePackageList(c, list);
}
}
@@ -566,8 +566,17 @@ func serveDoc(c *http.Conn, path string) {
// ----------------------------------------------------------------------------
// Server
+func makeFixedFileServer(filename string) (func(c *http.Conn, path string)) {
+ return func(c *http.Conn, path string) {
+ // ignore path and always serve the same file
+ // TODO this should be serveFile but there are some issues with *root
+ serveHTMLFile(c, filename);
+ };
+}
+
+
func installHandler(prefix string, handler func(c *http.Conn, path string)) {
- // customized handler with prefix
+ // create a handler customized with prefix
f := func(c *http.Conn, req *http.Request) {
path := req.Url.Path;
if *verbose {
@@ -604,13 +613,15 @@ func main() {
}
makePackageMap();
-
+
+ installHandler("/mem", makeFixedFileServer(GOROOT + "/doc/go_mem.html"));
+ installHandler("/spec", makeFixedFileServer(GOROOT + "/doc/go_spec.html"));
installHandler(docPrefix, serveDoc);
- installHandler(srcPrefix, serveSrc);
+ installHandler(filePrefix, serveFile);
+
{ err := http.ListenAndServe(":" + *port, nil);
if err != nil {
log.Exitf("ListenAndServe: %v", err)
}
}
}
-
diff --git a/usr/gri/pretty/pretty.go b/usr/gri/pretty/pretty.go
index fe2a03ecb..1c0f2445d 100644
--- a/usr/gri/pretty/pretty.go
+++ b/usr/gri/pretty/pretty.go
@@ -50,7 +50,7 @@ func print(prog *ast.Program) {
// initialize printer
var printer astPrinter.Printer;
- printer.Init(writer, prog.Comments, *html);
+ printer.Init(writer, nil, prog.Comments, *html);
printer.DoProgram(prog);