blob: 31be0076a3e1ec74d03cf8dce7d230637f281bd6 [file] [log] [blame]
David K. Bainbridge528b3182017-01-23 08:51:59 -08001package vtclean
2
3import (
4 "bufio"
5 "bytes"
6 "io"
7)
8
9type reader struct {
10 io.Reader
11 scanner *bufio.Scanner
12 buf []byte
13
14 color bool
15}
16
17func NewReader(r io.Reader, color bool) io.Reader {
18 return &reader{Reader: r, color: color}
19}
20
21func (r *reader) scan() bool {
22 if r.scanner == nil {
23 r.scanner = bufio.NewScanner(r.Reader)
24 }
25 if len(r.buf) > 0 {
26 return true
27 }
28 if r.scanner.Scan() {
29 r.buf = []byte(Clean(r.scanner.Text(), r.color) + "\n")
30 return true
31 }
32 return false
33}
34
35func (r *reader) fill(p []byte) int {
36 n := len(r.buf)
37 copy(p, r.buf)
38 if len(p) < len(r.buf) {
39 r.buf = r.buf[len(p):]
40 n = len(p)
41 } else {
42 r.buf = nil
43 }
44 return n
45}
46
47func (r *reader) Read(p []byte) (int, error) {
48 n := r.fill(p)
49 if n < len(p) {
50 if !r.scan() {
51 if n == 0 {
52 return 0, io.EOF
53 }
54 return n, nil
55 }
56 n += r.fill(p[n:])
57 }
58 return n, nil
59}
60
61type writer struct {
62 io.Writer
63 buf []byte
64 color bool
65}
66
67func NewWriter(w io.Writer, color bool) io.WriteCloser {
68 return &writer{Writer: w, color: color}
69}
70
71func (w *writer) Write(p []byte) (int, error) {
72 buf := append(w.buf, p...)
73 lines := bytes.Split(buf, []byte("\n"))
74 if len(lines) > 0 {
75 last := len(lines) - 1
76 w.buf = lines[last]
77 count := 0
78 for _, line := range lines[:last] {
79 n, err := w.Writer.Write([]byte(Clean(string(line), w.color) + "\n"))
80 count += n
81 if err != nil {
82 return count, err
83 }
84 }
85 }
86 return len(p), nil
87}
88
89func (w *writer) Close() error {
90 cl := Clean(string(w.buf), w.color)
91 _, err := w.Writer.Write([]byte(cl))
92 return err
93}