From 7fcf4221812c8e875b4ff56632b82d2d0f560519 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 17 Dec 2009 14:10:49 -0800 Subject: [PATCH] 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 --- src/cmd/godoc/godoc.go | 72 ++++++++++++++++++++++++++++++++++++++++-- 1 file 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 @@ -453,16 +453,84 @@ 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) } -- 2.48.1