github.com/v2fly/tools@v0.100.0/godoc/tab.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // TODO(bradfitz,adg): move to util 6 7 package godoc 8 9 import "io" 10 11 var spaces = []byte(" ") // 32 spaces seems like a good number 12 13 const ( 14 indenting = iota 15 collecting 16 ) 17 18 // A tconv is an io.Writer filter for converting leading tabs into spaces. 19 type tconv struct { 20 output io.Writer 21 state int // indenting or collecting 22 indent int // valid if state == indenting 23 p *Presentation 24 } 25 26 func (p *tconv) writeIndent() (err error) { 27 i := p.indent 28 for i >= len(spaces) { 29 i -= len(spaces) 30 if _, err = p.output.Write(spaces); err != nil { 31 return 32 } 33 } 34 // i < len(spaces) 35 if i > 0 { 36 _, err = p.output.Write(spaces[0:i]) 37 } 38 return 39 } 40 41 func (p *tconv) Write(data []byte) (n int, err error) { 42 if len(data) == 0 { 43 return 44 } 45 pos := 0 // valid if p.state == collecting 46 var b byte 47 for n, b = range data { 48 switch p.state { 49 case indenting: 50 switch b { 51 case '\t': 52 p.indent += p.p.TabWidth 53 case '\n': 54 p.indent = 0 55 if _, err = p.output.Write(data[n : n+1]); err != nil { 56 return 57 } 58 case ' ': 59 p.indent++ 60 default: 61 p.state = collecting 62 pos = n 63 if err = p.writeIndent(); err != nil { 64 return 65 } 66 } 67 case collecting: 68 if b == '\n' { 69 p.state = indenting 70 p.indent = 0 71 if _, err = p.output.Write(data[pos : n+1]); err != nil { 72 return 73 } 74 } 75 } 76 } 77 n = len(data) 78 if pos < n && p.state == collecting { 79 _, err = p.output.Write(data[pos:]) 80 } 81 return 82 }