From a6729b3085d764b845de505606008311860512b7 Mon Sep 17 00:00:00 2001
From: Volker Dobler
") html_endpre = []byte("\n") + html_h = []byte("
. // Turn each run of indented lines into a
block without indent. +// Enclose headings with header tags. // // URLs in the comment text are converted into links; if the URL also appears // in the words map, the link is taken from the map (if the corresponding map @@ -286,6 +338,8 @@ func unindent(block [][]byte) { // into a link. func ToHTML(w io.Writer, s []byte, words map[string]string) { inpara := false + lastWasBlank := false + lastNonblankWasHeading := false close := func() { if inpara { @@ -308,6 +362,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { // close paragraph close() i++ + lastWasBlank = true continue } if indentLen(line) > 0 { @@ -336,8 +391,27 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { w.Write(html_endpre) continue } + + if lastWasBlank && !lastNonblankWasHeading && i+2 < len(lines) && + isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 { + // current line is non-blank, sourounded by blank lines + // and the next non-blank line is not indented: this + // might be a heading. + if head := heading(line); head != nil { + close() + w.Write(html_h) + template.HTMLEscape(w, head) + w.Write(html_endh) + i += 2 + lastNonblankWasHeading = true + continue + } + } + // open paragraph open() + lastWasBlank = false + lastNonblankWasHeading = false emphasize(w, lines[i], words, true) // nice text formatting i++ } diff --git a/src/pkg/go/doc/comment_test.go b/src/pkg/go/doc/comment_test.go new file mode 100644 index 00000000000..9e77ae2cdea --- /dev/null +++ b/src/pkg/go/doc/comment_test.go @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +package doc + +import ( + "testing" +) + +var headingTests = []struct { + line string + ok bool +}{ + {"Section", true}, + {"A typical usage", true}, + {"ΔΛΞ is Greek", true}, + {"Foo 42", true}, + {"", false}, + {"section", false}, + {"A typical usage:", true}, + {"δ is Greek", false}, // TODO: consider allowing this + {"Foo §", false}, + {"Fermat's Last Sentence", true}, + {"Fermat's", true}, + {"'sX", false}, + {"Ted 'Too' Bar", false}, + {"Use n+m", false}, + {"Scanning:", true}, + {"N:M", false}, +} + +func TestIsHeading(t *testing.T) { + for _, tt := range headingTests { + if h := heading([]byte(tt.line)); (h != nil) != tt.ok { + t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok) + } + } +} diff --git a/src/pkg/go/doc/headscan.go b/src/pkg/go/doc/headscan.go new file mode 100644 index 00000000000..95953b3bdcb --- /dev/null +++ b/src/pkg/go/doc/headscan.go @@ -0,0 +1,53 @@ +package main + +import ( + "bytes" + "flag" + "go/doc" + "go/parser" + "go/token" + "log" + "os" + "path/filepath" + "strings" +) + +func isGoFile(fi os.FileInfo) bool { + return strings.HasSuffix(fi.Name(), ".go") && + !strings.HasSuffix(fi.Name(), "_test.go") +} + +func main() { + fset := token.NewFileSet() + rootDir := flag.String("root", "./", "root of filesystem tree to scan") + flag.Parse() + err := filepath.Walk(*rootDir, func(path string, fi os.FileInfo, err error) error { + if !fi.IsDir() { + return nil + } + pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments) + if err != nil { + log.Println(path, err) + return nil + } + for _, pkg := range pkgs { + d := doc.NewPackageDoc(pkg, path) + buf := new(bytes.Buffer) + doc.ToHTML(buf, []byte(d.Doc), nil) + b := buf.Bytes() + for { + i := bytes.Index(b, []byte("")) + if i == -1 { + break + } + line := bytes.SplitN(b[i:], []byte("\n"), 2)[0] + log.Printf("%s: %s", path, line) + b = b[i+len(line):] + } + } + return nil + }) + if err != nil { + log.Fatal(err) + } +}