You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
1.6 KiB

  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. // TODO(bradfitz,adg): move to util
  5. package godoc
  6. import "io"
  7. var spaces = []byte(" ") // 32 spaces seems like a good number
  8. const (
  9. indenting = iota
  10. collecting
  11. )
  12. // A tconv is an io.Writer filter for converting leading tabs into spaces.
  13. type tconv struct {
  14. output io.Writer
  15. state int // indenting or collecting
  16. indent int // valid if state == indenting
  17. p *Presentation
  18. }
  19. func (p *tconv) writeIndent() (err error) {
  20. i := p.indent
  21. for i >= len(spaces) {
  22. i -= len(spaces)
  23. if _, err = p.output.Write(spaces); err != nil {
  24. return
  25. }
  26. }
  27. // i < len(spaces)
  28. if i > 0 {
  29. _, err = p.output.Write(spaces[0:i])
  30. }
  31. return
  32. }
  33. func (p *tconv) Write(data []byte) (n int, err error) {
  34. if len(data) == 0 {
  35. return
  36. }
  37. pos := 0 // valid if p.state == collecting
  38. var b byte
  39. for n, b = range data {
  40. switch p.state {
  41. case indenting:
  42. switch b {
  43. case '\t':
  44. p.indent += p.p.TabWidth
  45. case '\n':
  46. p.indent = 0
  47. if _, err = p.output.Write(data[n : n+1]); err != nil {
  48. return
  49. }
  50. case ' ':
  51. p.indent++
  52. default:
  53. p.state = collecting
  54. pos = n
  55. if err = p.writeIndent(); err != nil {
  56. return
  57. }
  58. }
  59. case collecting:
  60. if b == '\n' {
  61. p.state = indenting
  62. p.indent = 0
  63. if _, err = p.output.Write(data[pos : n+1]); err != nil {
  64. return
  65. }
  66. }
  67. }
  68. }
  69. n = len(data)
  70. if pos < n && p.state == collecting {
  71. _, err = p.output.Write(data[pos:])
  72. }
  73. return
  74. }