diff options
author | Robert Griesemer <gri@golang.org> | 2009-04-02 15:58:58 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-04-02 15:58:58 -0700 |
commit | d20ad3543bc9a4bfc11d6f4a61a8466dc4444de1 (patch) | |
tree | 72750b4cbbea688539f1aacb44e8a24200e05f7c | |
parent | 63fe0852470628233b332923ca23a261c6ca3bc9 (diff) | |
download | golang-d20ad3543bc9a4bfc11d6f4a61a8466dc4444de1.tar.gz |
- adjustments for changed AST
- renamed gds -> godoc
- functionality to find and serve packages
(to get a list of packages provide dir path + "?p")
Next steps: cleanups, better formatting, fine-tuning of output
R=r
OCL=27037
CL=27039
-rw-r--r-- | usr/gri/pretty/Makefile | 8 | ||||
-rw-r--r-- | usr/gri/pretty/astprinter.go | 14 | ||||
-rw-r--r-- | usr/gri/pretty/docprinter.go | 16 | ||||
-rw-r--r-- | usr/gri/pretty/gds.go | 235 | ||||
-rw-r--r-- | usr/gri/pretty/godoc.go | 443 | ||||
-rw-r--r-- | usr/gri/pretty/packages_template.html | 10 | ||||
-rw-r--r-- | usr/gri/pretty/template.go | 2 |
7 files changed, 473 insertions, 255 deletions
diff --git a/usr/gri/pretty/Makefile b/usr/gri/pretty/Makefile index ed2866473..43dea4807 100644 --- a/usr/gri/pretty/Makefile +++ b/usr/gri/pretty/Makefile @@ -5,13 +5,13 @@ G=6g L=6l -all: untab gds pretty +all: untab godoc pretty untab: untab.6 $(L) -o untab untab.6 -gds: gds.6 - $(L) -o gds gds.6 +godoc: godoc.6 + $(L) -o godoc godoc.6 pretty: pretty.6 $(L) -o pretty pretty.6 @@ -28,7 +28,7 @@ install: pretty clean: rm -f pretty *.6 *.a *~ -gds.6: utils.6 platform.6 compilation.6 docprinter.6 +godoc.6: utils.6 platform.6 compilation.6 docprinter.6 pretty.6: platform.6 ast.6 astprinter.6 compilation.6 diff --git a/usr/gri/pretty/astprinter.go b/usr/gri/pretty/astprinter.go index 828ec5ad9..5164495fe 100644 --- a/usr/gri/pretty/astprinter.go +++ b/usr/gri/pretty/astprinter.go @@ -60,7 +60,7 @@ func assert(pred bool) { // TODO this should be an AST method func isExported(name *ast.Ident) bool { - ch, len := utf8.DecodeRune(name.Lit); + ch, len := utf8.DecodeRuneInString(name.Value, 0); return unicode.IsUpper(ch); } @@ -405,7 +405,7 @@ func (P *Printer) Error(pos token.Position, tok token.Token, msg string) { // HTML support func (P *Printer) HtmlIdentifier(x *ast.Ident) { - P.String(x.Pos(), string(x.Lit)); + P.String(x.Pos(), x.Value); /* obj := x.Obj; if P.html && obj.Kind != symbolTable.NONE { @@ -620,25 +620,25 @@ func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) { func (P *Printer) DoIntLit(x *ast.IntLit) { // TODO get rid of string conversion here - P.String(x.Pos(), string(x.Lit)); + P.String(x.Pos(), string(x.Value)); } func (P *Printer) DoFloatLit(x *ast.FloatLit) { // TODO get rid of string conversion here - P.String(x.Pos(), string(x.Lit)); + P.String(x.Pos(), string(x.Value)); } func (P *Printer) DoCharLit(x *ast.CharLit) { // TODO get rid of string conversion here - P.String(x.Pos(), string(x.Lit)); + P.String(x.Pos(), string(x.Value)); } func (P *Printer) DoStringLit(x *ast.StringLit) { // TODO get rid of string conversion here - P.String(x.Pos(), string(x.Lit)); + P.String(x.Pos(), string(x.Value)); } @@ -1120,7 +1120,7 @@ func (P *Printer) importSpec(d *ast.ImportSpec) { } P.separator = tab; // TODO fix for longer package names - P.HtmlPackageName(d.Path[0].Pos(), string(d.Path[0].Lit)); + P.HtmlPackageName(d.Path[0].Pos(), string(d.Path[0].Value)); P.newlines = 2; } diff --git a/usr/gri/pretty/docprinter.go b/usr/gri/pretty/docprinter.go index 05b8f3e50..f9737a790 100644 --- a/usr/gri/pretty/docprinter.go +++ b/usr/gri/pretty/docprinter.go @@ -23,7 +23,7 @@ import ( // TODO this should be an AST method func isExported(name *ast.Ident) bool { - ch, len := utf8.DecodeRune(name.Lit); + ch, len := utf8.DecodeRuneInString(name.Value, 0); return unicode.IsUpper(ch); } @@ -92,7 +92,7 @@ func (doc *PackageDoc) Init(name string) { func baseTypeName(typ ast.Expr) string { switch t := typ.(type) { case *ast.Ident: - return string(t.Lit); + return string(t.Value); case *ast.StarExpr: return baseTypeName(t.X); } @@ -111,14 +111,14 @@ func (doc *PackageDoc) lookupTypeDoc(typ ast.Expr) *typeDoc { func (doc *PackageDoc) addType(decl *ast.GenDecl) { typ := decl.Specs[0].(*ast.TypeSpec); - name := string(typ.Name.Lit); + name := typ.Name.Value; tdoc := &typeDoc{decl, make(map[string] *funcDoc), make(map[string] *funcDoc)}; doc.types[name] = tdoc; } func (doc *PackageDoc) addFunc(fun *ast.FuncDecl) { - name := string(fun.Name.Lit); + name := fun.Name.Value; fdoc := &funcDoc{fun}; // determine if it should be associated with a type @@ -197,7 +197,7 @@ func (doc *PackageDoc) addDecl(decl ast.Decl) { // before, AddProgram is a no-op. // func (doc *PackageDoc) AddProgram(prog *ast.Program) { - if doc.name != string(prog.Name.Lit) { + if doc.name != prog.Name.Value { panic("package names don't match"); } @@ -387,9 +387,9 @@ func (f *funcDoc) print(p *astPrinter.Printer, hsize int) { if d.Recv != nil { p.Printf("<h%d>func (", hsize); p.Expr(d.Recv.Type); - p.Printf(") %s</h%d>\n", d.Name.Lit, hsize); + p.Printf(") %s</h%d>\n", d.Name.Value, hsize); } else { - p.Printf("<h%d>func %s</h%d>\n", hsize, d.Name.Lit, hsize); + p.Printf("<h%d>func %s</h%d>\n", hsize, d.Name.Value, hsize); } p.Printf("<p><code>"); p.DoFuncDecl(d); @@ -401,7 +401,7 @@ func (f *funcDoc) print(p *astPrinter.Printer, hsize int) { func (t *typeDoc) print(p *astPrinter.Printer) { d := t.decl; s := d.Specs[0].(*ast.TypeSpec); - p.Printf("<h2>type %s</h2>\n", string(s.Name.Lit)); + p.Printf("<h2>type %s</h2>\n", s.Name.Value); p.Printf("<p><pre>"); p.DoGenDecl(d); p.Printf("</pre></p>\n"); diff --git a/usr/gri/pretty/gds.go b/usr/gri/pretty/gds.go deleted file mode 100644 index a004ad223..000000000 --- a/usr/gri/pretty/gds.go +++ /dev/null @@ -1,235 +0,0 @@ -// 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. - -// GDS: Go Documentation Server - -package main - -import ( - "bufio"; - "flag"; - "fmt"; - "http"; - "io"; - "net"; - "os"; - "sort"; - "log"; - "template"; - "tabwriter"; - - "utils"; - "platform"; - "compilation"; - "docprinter"; -) - - -var ( - verbose = flag.Bool("v", false, "verbose mode"); - port = flag.String("port", "6060", "server port"); - root = flag.String("root", Platform.GOROOT, "go root directory"); - - // layout control - tabwidth = flag.Int("tabwidth", 4, "tab width"); - usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks"); -) - - -// Support for directory sorting. -type DirArray []os.Dir -func (p DirArray) Len() int { return len(p); } -func (p DirArray) Less(i, j int) bool { return p[i].Name < p[j].Name; } -func (p DirArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; } - - -func isGoFile(dir *os.Dir) bool { - const ext = ".go"; - return dir.IsRegular() && Utils.Contains(dir.Name, ext, len(dir.Name) - len(ext)); -} - - -func printLink(c *http.Conn, path, name string) { - fmt.Fprintf(c, "<a href=\"%s\">%s</a><br />\n", path + name, name); -} - - -var dir_template = template.NewTemplateOrDie("dir_template.html"); - -func serveDir(c *http.Conn, dirname string) { - fd, err1 := os.Open(*root + dirname, os.O_RDONLY, 0); - if err1 != nil { - c.WriteHeader(http.StatusNotFound); - fmt.Fprintf(c, "Error: %v (%s)\n", err1, dirname); - return; - } - - list, err2 := fd.Readdir(-1); - if err2 != nil { - c.WriteHeader(http.StatusNotFound); - fmt.Fprintf(c, "Error: %v (%s)\n", err2, dirname); - return; - } - - 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 - dir_template.Apply(c, "<!--", template.Substitution { - "PATH-->" : func() { - fmt.Fprintf(c, "%s", path); - }, - - "DIRECTORIES-->" : func() { - for i, entry := range list { - if entry.IsDirectory() { - printLink(c, path, entry.Name); - } - } - }, - - "GO FILES-->" : func() { - for i, entry := range list { - if isGoFile(&entry) { - printLink(c, path, entry.Name); - } - } - }, - - "OTHER FILES-->" : func() { - for i, entry := range list { - if !entry.IsDirectory() && !isGoFile(&entry) { - fmt.Fprintf(c, "%s<br />\n", entry.Name); - } - } - } - }); -} - - -var error_template = template.NewTemplateOrDie("error_template.html"); - -func printErrors(c *http.Conn, filename string, errors Compilation.ErrorList) { - // TODO factor code - shouldn't do this here and in Compilation - src, ok := Platform.ReadSourceFile(*root + filename); - - // TODO handle Apply errors - error_template.Apply(c, "<!--", template.Substitution { - "FILE_NAME-->" : func() { - fmt.Fprintf(c, "%s", filename); - }, - - "ERRORS-->" : func () { - if ok == false /* 6g bug139 */ { - fmt.Fprintf(c, "could not read file %s\n", *root + filename); - return; - } - 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)]); - } - }); -} - - -func serveFile(c *http.Conn, filename string) { - var flags Compilation.Flags; - prog, errors := Compilation.Compile(*root + filename, &flags); - if errors == nil { - c.WriteHeader(http.StatusNotFound); - fmt.Fprintf(c, "Error: could not read file (%s)\n", filename); - return; - } - - if len(errors) > 0 { - c.SetHeader("content-type", "text/html; charset=utf-8"); - printErrors(c, filename, errors); - return; - } - - c.SetHeader("content-type", "text/html; charset=utf-8"); - - // initialize tabwriter for nicely aligned output - padchar := byte(' '); - if *usetabs { - padchar = '\t'; - } - writer := tabwriter.NewWriter(c, *tabwidth, 1, padchar, tabwriter.FilterHTML); - - // write documentation - var doc docPrinter.PackageDoc; - doc.Init(string(prog.Name.Lit)); - doc.AddProgram(prog); - doc.Print(writer); - - // flush any pending output - err := writer.Flush(); - if err != nil { - panic("print error - exiting"); - } -} - - -func serve(c *http.Conn, req *http.Request) { - if *verbose { - log.Stdoutf("URL = %s\n", req.RawUrl); - } - - path := Utils.SanitizePath(req.Url.Path); - dir, err := os.Stat(*root + path); - if err != nil { - c.WriteHeader(http.StatusNotFound); - fmt.Fprintf(c, "Error: %v (%s)\n", err, path); - return; - } - - switch { - case dir.IsDirectory(): - serveDir(c, path); - case isGoFile(dir): - serveFile(c, path); - default: - c.WriteHeader(http.StatusNotFound); - fmt.Fprintf(c, "Error: Not a directory or .go file (%s)\n", path); - } -} - - -func main() { - flag.Parse(); - - *root = Utils.SanitizePath(*root); - dir, err1 := os.Stat(*root); - if err1 != nil || !dir.IsDirectory() { - log.Exitf("root not found or not a directory: %s", *root); - } - - if *verbose { - log.Stdoutf("Go Documentation Server\n"); - log.Stdoutf("port = %s\n", *port); - log.Stdoutf("root = %s\n", *root); - } - - http.Handle("/", http.HandlerFunc(serve)); - err2 := http.ListenAndServe(":" + *port, nil); - if err2 != nil { - log.Exitf("ListenAndServe: %s", err2.String()) - } -} - diff --git a/usr/gri/pretty/godoc.go b/usr/gri/pretty/godoc.go new file mode 100644 index 000000000..13e58bd6c --- /dev/null +++ b/usr/gri/pretty/godoc.go @@ -0,0 +1,443 @@ +// 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: Go Documentation Server + +package main + +import ( + "bufio"; + "flag"; + "fmt"; + "http"; + "io"; + "log"; + "net"; + "os"; + "sort"; + "tabwriter"; + "template"; + "regexp"; + + "ast"; + "vector"; + "utils"; + "platform"; + "compilation"; + "parser"; + "docprinter"; +) + + +var ( + verbose = flag.Bool("v", false, "verbose mode"); + port = flag.String("port", "6060", "server port"); + root = flag.String("root", Platform.GOROOT, "go root directory"); + + // layout control + tabwidth = flag.Int("tabwidth", 4, "tab width"); + usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks"); +) + + +// ---------------------------------------------------------------------------- +// Support + +type dirArray []os.Dir +func (p dirArray) Len() int { return len(p); } +func (p dirArray) Less(i, j int) bool { return p[i].Name < p[j].Name; } +func (p dirArray) Swap(i, j int) { p[i], p[j] = p[j], p[i]; } + + +func isGoFile(dir *os.Dir) bool { + const ext = ".go"; + return dir.IsRegular() && Utils.Contains(dir.Name, ext, len(dir.Name) - len(ext)); +} + + +func printLink(c *http.Conn, path, name string) { + fmt.Fprintf(c, "<a href=\"%s\">%s</a><br />\n", path + name, name); +} + + +func makeTabwriter(writer io.Write) *tabwriter.Writer { + padchar := byte(' '); + if *usetabs { + padchar = '\t'; + } + return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, tabwriter.FilterHTML); +} + + +// ---------------------------------------------------------------------------- +// Directories + +var dir_template = template.NewTemplateOrDie("dir_template.html"); + +func serveDir(c *http.Conn, dirname string) { + fd, err1 := os.Open(*root + dirname, os.O_RDONLY, 0); + if err1 != nil { + c.WriteHeader(http.StatusNotFound); + fmt.Fprintf(c, "Error: %v (%s)\n", err1, dirname); + return; + } + + list, err2 := fd.Readdir(-1); + if err2 != nil { + c.WriteHeader(http.StatusNotFound); + fmt.Fprintf(c, "Error: %v (%s)\n", err2, dirname); + return; + } + + 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 + dir_template.Apply(c, "<!--", template.Substitution { + "PATH-->" : func() { + fmt.Fprintf(c, "%s", path); + }, + + "DIRECTORIES-->" : func() { + for i, entry := range list { + if entry.IsDirectory() { + printLink(c, path, entry.Name); + } + } + }, + + "GO FILES-->" : func() { + for i, entry := range list { + if isGoFile(&entry) { + printLink(c, path, entry.Name); + } + } + }, + + "OTHER FILES-->" : func() { + for i, entry := range list { + if !entry.IsDirectory() && !isGoFile(&entry) { + fmt.Fprintf(c, "%s<br />\n", entry.Name); + } + } + } + }); +} + + +// ---------------------------------------------------------------------------- +// Files + +var error_template = template.NewTemplateOrDie("error_template.html"); + +func printErrors(c *http.Conn, filename string, errors Compilation.ErrorList) { + // TODO factor code - shouldn't do this here and in Compilation + src, ok := Platform.ReadSourceFile(*root + filename); + + // TODO handle Apply errors + error_template.Apply(c, "<!--", template.Substitution { + "FILE_NAME-->" : func() { + fmt.Fprintf(c, "%s", filename); + }, + + "ERRORS-->" : func () { + if ok == false /* 6g bug139 */ { + fmt.Fprintf(c, "could not read file %s\n", *root + filename); + return; + } + 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)]); + } + }); +} + + +func serveGoFile(c *http.Conn, dirname string, filenames []string) { + // compute documentation + var doc docPrinter.PackageDoc; + for i, filename := range filenames { + var flags Compilation.Flags; + prog, errors := Compilation.Compile(*root + "/" + dirname + "/" + filename, &flags); + if errors == nil { + c.WriteHeader(http.StatusNotFound); + fmt.Fprintf(c, "Error: could not read file (%s)\n", filename); + return; + } + + 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); + } + + c.SetHeader("content-type", "text/html; charset=utf-8"); + + // write documentation + writer := makeTabwriter(c); // for nicely formatted output + doc.Print(writer); + writer.Flush(); // ignore errors +} + + +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); + return; + } + + switch { + case dir.IsDirectory(): + serveDir(c, path); + case isGoFile(dir): + serveGoFile(c, "", []string{path}); + default: + c.WriteHeader(http.StatusNotFound); + fmt.Fprintf(c, "Error: Not a directory or .go file (%s)\n", path); + } +} + + +// ---------------------------------------------------------------------------- +// Packages + +type pakDesc struct { + dirname string; // local to *root + pakname string; // local to directory + filenames map[string] bool; // set of file (names) belonging to this package +} + + +type pakArray []*pakDesc +func (p pakArray) Len() int { return len(p); } +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 +) + + +func getAST(dirname string, filename string, mode uint) *ast.Program { + // open file + fullname := *root + "/" + dirname + "/" + filename; + src, err := os.Open(fullname, os.O_RDONLY, 0); + defer src.Close(); + if err != nil { + log.Stdoutf("%s: %v", fullname, err); + return nil; + } + + // determine package name + prog, ok := parser.Parse(src, nil, mode); + if !ok { + log.Stdoutf("%s: compilation errors", fullname); + return nil; + } + + return prog; +} + + +func addFile(dirname string, filename string) { + // determine package name + prog := getAST(dirname, filename, parser.PackageClauseOnly); + if prog == nil { + return; + } + if prog.Name.Value == "main" { + // ignore main packages for now + return; + } + pakname := dirname + "/" + prog.Name.Value; + + // find package descriptor + pakdesc, found := pakMap[pakname]; + if !found { + // add a new descriptor + pakdesc = &pakDesc{dirname, prog.Name.Value, make(map[string]bool)}; + pakMap[pakname] = pakdesc; + } + + //fmt.Printf("pak = %s, file = %s\n", pakname, filename); + + // add file to package desc + if tmp, found := pakdesc.filenames[filename]; found { + panic("internal error: same file added more then once: " + filename); + } + pakdesc.filenames[filename] = true; +} + + +func addDirectory(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); + return; + } + + list, err2 := fd.Readdir(-1); + if err2 != nil { + log.Stdoutf("%s: %v", *root + dirname, err2); + return; + } + + for i, entry := range list { + switch { + case entry.IsDirectory(): + if entry.Name != "." && entry.Name != ".." { + addDirectory(dirname + "/" + entry.Name); + } + case isGoFile(&entry): + //fmt.Printf("found %s/%s\n", dirname, entry.Name); + addFile(dirname, entry.Name); + } + } +} + + +func makePackageMap() { + // TODO shold do this under a lock, eventually + // populate package map + pakMap = make(map[string]*pakDesc); + addDirectory(""); + + // build sorted package list + pakList = make([]*pakDesc, len(pakMap)); + i := 0; + for tmp, pakdesc := range pakMap { + pakList[i] = pakdesc; + i++; + } + sort.Sort(pakList); +} + + +var packages_template = template.NewTemplateOrDie("packages_template.html"); + +func serveGoPackage(c *http.Conn, p *pakDesc) { + // make a filename list + list := make([]string, len(p.filenames)); + i := 0; + for filename, tmp := range p.filenames { + list[i] = filename; + i++; + } + + serveGoFile(c, p.dirname, list); +} + + +func servePackageList(c *http.Conn, list *vector.Vector) { + packages_template.Apply(c, "<!--", template.Substitution { + "PACKAGE_LIST-->" : 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", link + "?p", p.pakname, link); + } + } + }); +} + + +func servePackage(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); + } + + // build list of matching packages + list := vector.New(0); + for i, p := range pakList { + if rex.Match(p.dirname + "/" + p.pakname) { + list.Push(p); + } + } + + if list.Len() == 1 { + serveGoPackage(c, list.At(0).(*pakDesc)); + } else { + servePackageList(c, list); + } +} + + +// ---------------------------------------------------------------------------- +// Server + +func serve(c *http.Conn, req *http.Request) { + if *verbose { + log.Stdoutf("%s\t%s", req.Host, req.RawUrl); + } + + path := Utils.SanitizePath(req.Url.Path); + + if len(req.Url.Query) > 0 { // for now any query will do + servePackage(c, path); + } else { + serveFile(c, path); + } +} + + +func main() { + flag.Parse(); + + *root = Utils.SanitizePath(*root); + { dir, err := os.Stat(*root); + if err != nil || !dir.IsDirectory() { + log.Exitf("root not found or not a directory: %s", *root); + } + } + + if *verbose { + log.Stdoutf("Go Documentation Server\n"); + log.Stdoutf("port = %s\n", *port); + log.Stdoutf("root = %s\n", *root); + } + + makePackageMap(); + + http.Handle("/", http.HandlerFunc(serve)); + { err := http.ListenAndServe(":" + *port, nil); + if err != nil { + log.Exitf("ListenAndServe: %v", err) + } + } +} + diff --git a/usr/gri/pretty/packages_template.html b/usr/gri/pretty/packages_template.html new file mode 100644 index 000000000..552ce6220 --- /dev/null +++ b/usr/gri/pretty/packages_template.html @@ -0,0 +1,10 @@ + +<font color=red>THIS SECTION IS CURRENTLY UNDER CONSTRUCTION</font> + +<h1>Packages</h1> + +<!--PACKAGE_LIST--> + +</div> <!-- content --> +</body> +</html> diff --git a/usr/gri/pretty/template.go b/usr/gri/pretty/template.go index 6b70c66a7..9aa83d449 100644 --- a/usr/gri/pretty/template.go +++ b/usr/gri/pretty/template.go @@ -117,7 +117,7 @@ func NewTemplate(filename string) *Template { func NewTemplateOrDie(filename string) *Template { t := NewTemplate(filename); if t == nil { - panic("could not read template"); + panic("could not read template: " + filename); } return t; } |