-
Notifications
You must be signed in to change notification settings - Fork 6
/
writer.go
71 lines (62 loc) · 1.42 KB
/
writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package goterminal
import (
"bytes"
"io"
"sync"
)
const esc = 27
// termWidth marks the boundary of UI, beyond which text written should go to next line.
var termWidth int
// Writer represents the IO writer which updates the UI and holds the buffer.
type Writer struct {
Out io.Writer
Buf bytes.Buffer
lineCount int
mtx sync.Mutex
}
// New returns a new instance of the Writer. It initializes the terminal width and buffer.
func New(out io.Writer) *Writer {
writer := &Writer{Out: out}
if termWidth == 0 {
termWidth, _ = writer.GetTermDimensions()
}
return writer
}
// Reset resets the Writer.
func (w *Writer) Reset() {
w.mtx.Lock()
defer w.mtx.Unlock()
w.Buf.Reset()
w.lineCount = 0
}
// Print writes the buffer contents to Out and resets the buffer.
// It stores the number of lines to go up the Writer in the Writer.lineCount.
func (w *Writer) Print() error {
w.mtx.Lock()
defer w.mtx.Unlock()
// do nothing if buffer is empty
if len(w.Buf.Bytes()) == 0 {
return nil
}
var currentLine bytes.Buffer
for _, b := range w.Buf.Bytes() {
if b == '\n' {
w.lineCount++
currentLine.Reset()
} else {
currentLine.Write([]byte{b})
if currentLine.Len() > termWidth {
w.lineCount++
currentLine.Reset()
}
}
}
_, err := w.Out.Write(w.Buf.Bytes())
w.Buf.Reset()
return err
}
func (w *Writer) Write(b []byte) (int, error) {
w.mtx.Lock()
defer w.mtx.Unlock()
return w.Buf.Write(b)
}