aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2009-12-17 14:10:49 -0800
committerRobert Griesemer <gri@golang.org>2009-12-17 14:10:49 -0800
commit7fcf4221812c8e875b4ff56632b82d2d0f560519 (patch)
tree7d506420bf5c12e1450536b83d7e2f53447202db
parentd2a835fbf3f22ca3b3e5fb51c8c2756c8a7b2550 (diff)
downloadgo-7fcf4221812c8e875b4ff56632b82d2d0f560519.tar.gz
go-7fcf4221812c8e875b4ff56632b82d2d0f560519.zip
use new tab indentation format in godoc, but convert
leading tabs into spaces to ensure a good outcome in most browsers R=rsc https://golang.org/cl/165051
-rw-r--r--src/cmd/godoc/godoc.go72
1 files changed, 70 insertions, 2 deletions
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 1e4eb1625b..a381c3a586 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -454,15 +454,83 @@ func (s *Styler) Token(tok token.Token) (text []byte, tag printer.HTMLTag) {
// ----------------------------------------------------------------------------
+// Tab conversion
+
+var spaces = strings.Bytes(" ") // 16 spaces seems like a good number
+
+const (
+ indenting = iota
+ collecting
+)
+
+// A tconv is an io.Writer filter for converting leading tabs into spaces.
+type tconv struct {
+ output io.Writer
+ state int // indenting or collecting
+ indent int // valid if state == indenting
+}
+
+
+func (p *tconv) writeIndent(n int) (err os.Error) {
+ i := n * *tabwidth
+ for i > len(spaces) {
+ i -= len(spaces)
+ if _, err = p.output.Write(spaces); err != nil {
+ return
+ }
+ }
+ _, err = p.output.Write(spaces[0:i])
+ return
+}
+
+
+func (p *tconv) Write(data []byte) (n int, err os.Error) {
+ pos := 0 // valid if p.state == collecting
+ var b byte
+ for n, b = range data {
+ switch p.state {
+ case indenting:
+ if b == '\t' {
+ p.indent++
+ } else {
+ p.state = collecting
+ pos = n
+ if err = p.writeIndent(p.indent); err != nil {
+ return
+ }
+ }
+ case collecting:
+ if b == '\n' {
+ p.state = indenting
+ p.indent = 0
+ if _, err = p.output.Write(data[pos : n+1]); err != nil {
+ return
+ }
+ }
+ }
+ }
+ n = len(data)
+ if p.state == collecting {
+ _, err = p.output.Write(data[pos:])
+ }
+ return
+}
+
+
+// ----------------------------------------------------------------------------
// Templates
// Write an AST-node to w; optionally html-escaped.
func writeNode(w io.Writer, node interface{}, html bool, styler printer.Styler) {
- mode := printer.UseSpaces | printer.NoSemis
+ mode := printer.TabIndent | printer.UseSpaces | printer.NoSemis
if html {
mode |= printer.GenHTML
}
- (&printer.Config{mode, *tabwidth, styler}).Fprint(w, node)
+ // convert trailing tabs into spaces using a tconv filter
+ // to ensure a good outcome in most browsers (there may still
+ // be tabs in comments and strings, but converting those into
+ // the right number of spaces is much harder)
+ (&printer.Config{mode, *tabwidth, styler}).Fprint(&tconv{output: w}, node)
}