internal/godoc: introduce TabSpacer
Mainly just isolate it from Presentation, but give it a nice API too.
Change-Id: I9650bf650a15bfd814fe4da58de6fa133a858d90
Reviewed-on: https://go-review.googlesource.com/c/website/+/296374
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/internal/godoc/godoc.go b/internal/godoc/godoc.go
index 25b3063..47c2b0f 100644
--- a/internal/godoc/godoc.go
+++ b/internal/godoc/godoc.go
@@ -605,7 +605,7 @@
}
mode := printer.TabIndent | printer.UseSpaces
- err := (&printer.Config{Mode: mode, Tabwidth: p.TabWidth}).Fprint(&tconv{p: p, output: out}, fset, x)
+ err := (&printer.Config{Mode: mode, Tabwidth: p.TabWidth}).Fprint(TabSpacer(out, p.TabWidth), fset, x)
if err != nil {
log.Print(err)
}
diff --git a/internal/godoc/tab.go b/internal/godoc/tab.go
index 944074e..17fe293 100644
--- a/internal/godoc/tab.go
+++ b/internal/godoc/tab.go
@@ -5,8 +5,6 @@
//go:build go1.16
// +build go1.16
-// TODO(bradfitz,adg): move to util
-
package godoc
import "io"
@@ -18,68 +16,74 @@
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
- p *Presentation
+// TabSpacer returns a writer that passes writes through to w,
+// expanding tabs to one or more spaces ending at a width-spaces-aligned boundary.
+func TabSpacer(w io.Writer, width int) io.Writer {
+ return &tconv{output: w, tabWidth: width}
}
-func (p *tconv) writeIndent() (err error) {
- i := p.indent
+// 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
+ tabWidth int
+}
+
+func (t *tconv) writeIndent() (err error) {
+ i := t.indent
for i >= len(spaces) {
i -= len(spaces)
- if _, err = p.output.Write(spaces); err != nil {
+ if _, err = t.output.Write(spaces); err != nil {
return
}
}
// i < len(spaces)
if i > 0 {
- _, err = p.output.Write(spaces[0:i])
+ _, err = t.output.Write(spaces[0:i])
}
return
}
-func (p *tconv) Write(data []byte) (n int, err error) {
+func (t *tconv) Write(data []byte) (n int, err error) {
if len(data) == 0 {
return
}
pos := 0 // valid if p.state == collecting
var b byte
for n, b = range data {
- switch p.state {
+ switch t.state {
case indenting:
switch b {
case '\t':
- p.indent += p.p.TabWidth
+ t.indent += t.tabWidth
case '\n':
- p.indent = 0
- if _, err = p.output.Write(data[n : n+1]); err != nil {
+ t.indent = 0
+ if _, err = t.output.Write(data[n : n+1]); err != nil {
return
}
case ' ':
- p.indent++
+ t.indent++
default:
- p.state = collecting
+ t.state = collecting
pos = n
- if err = p.writeIndent(); err != nil {
+ if err = t.writeIndent(); 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 {
+ t.state = indenting
+ t.indent = 0
+ if _, err = t.output.Write(data[pos : n+1]); err != nil {
return
}
}
}
}
n = len(data)
- if pos < n && p.state == collecting {
- _, err = p.output.Write(data[pos:])
+ if pos < n && t.state == collecting {
+ _, err = t.output.Write(data[pos:])
}
return
}