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 0000000000..9e77ae2cde
--- /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 0000000000..95953b3bdc
--- /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)
+ }
+}