-
Notifications
You must be signed in to change notification settings - Fork 1
/
buffer.go
174 lines (153 loc) · 4.03 KB
/
buffer.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package anansi
import (
"bytes"
"io"
"unicode/utf8"
"github.com/jcorbin/anansi/ansi"
)
// Buffer implements a deferred buffer of ANSI output, providing
// convenience methods for writing various ansi escape sequences, and keeping
// an observant processor up to date.
type Buffer struct {
buf bytes.Buffer
off int
}
// Len returns the number of unwritten bytes in the buffer.
func (b *Buffer) Len() int {
return b.buf.Len()
}
// Grow the internal buffer to have room for at least n bytes.
func (b *Buffer) Grow(n int) {
b.buf.Grow(n)
}
// Bytes returns a byte slice containing all bytes written into the internal
// buffer. Returned slice is only valid until the next call to a buffer method.
func (b *Buffer) Bytes() []byte {
return b.buf.Bytes()
}
// Reset the internal buffer.
func (b *Buffer) Reset() {
b.buf.Reset()
b.off = 0
}
// WriteTo writes all bytes from the internal buffer to the given io.Writer.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
n, err = b.buf.WriteTo(w)
if b.off -= int(n); b.off < 0 {
b.off = 0
}
return n, err
}
// WriteESC writes one or more ANSI escapes to the internal buffer, returning
// the number of bytes written.
func (b *Buffer) WriteESC(seqs ...ansi.Escape) int {
need := 0
for i := range seqs {
need += seqs[i].Size()
}
b.buf.Grow(need)
p := b.buf.Bytes()
p = p[len(p):]
for i := range seqs {
p = seqs[i].AppendTo(p)
}
n, _ := b.buf.Write(p)
return n
}
// WriteSeq writes one or more ANSI ansi.escape sequences to the internal
// buffer, returning the number of bytes written. Skips any zero sequences
// provided.
func (b *Buffer) WriteSeq(seqs ...ansi.Seq) int {
need := 0
for i := range seqs {
need += seqs[i].Size()
}
b.buf.Grow(need)
p := b.buf.Bytes()
p = p[len(p):]
for i := range seqs {
p = seqs[i].AppendTo(p)
}
n, _ := b.buf.Write(p)
return n
}
// WriteSGR writes one or more ANSI SGR sequences to the internal buffer,
// returning the number of bytes written; updates Attr cursor state. Skips any
// zero attr values (NOTE 0 attr value is merely implicit clear, not the
// explicit SGRAttrClear).
func (b *Buffer) WriteSGR(attrs ...ansi.SGRAttr) int {
need := 0
for i := range attrs {
if attrs[i] != 0 {
need += attrs[i].Size()
}
}
b.buf.Grow(need)
p := b.buf.Bytes()
p = p[len(p):]
for i := range attrs {
if attrs[i] != 0 {
p = attrs[i].AppendTo(p)
}
}
n, _ := b.buf.Write(p)
return n
}
// Write to the internal buffer.
func (b *Buffer) Write(p []byte) (n int, err error) {
return b.buf.Write(p)
}
// WriteString to the internal buffer.
func (b *Buffer) WriteString(s string) (n int, err error) {
return b.buf.WriteString(s)
}
// WriteRune to the internal buffer.
func (b *Buffer) WriteRune(r rune) (n int, err error) {
return b.buf.WriteRune(r)
}
// WriteByte to the internal buffer.
func (b *Buffer) WriteByte(c byte) error {
return b.buf.WriteByte(c)
}
// Skip Process()ing of n bytes written to the internal buffer. Useful when the
// processor wants to intermediate a buffer write, handling its own semantic
// update and avoiding (re)parsing the written bytes.
func (b *Buffer) Skip(n int) {
b.off += n
}
// Discard processed bytes, re-using internal buffer space during the next Write*.
func (b *Buffer) Discard() {
if b.off > 0 {
b.buf.Next(b.off)
b.off = 0
}
}
// Process bytes written to the internal buffer, decoding runes and escape
// sequences, and passing them to the given processor.
func (b *Buffer) Process(proc Processor) {
b.off += Process(proc, b.buf.Bytes()[b.off:])
}
// Process decodes ansi escapes and utf8 runes from p, passing them to proc.
func Process(proc Processor, p []byte) (n int) {
for n < len(p) {
e, a, m := ansi.DecodeEscape(p[n:])
n += m
if e == 0 {
switch r, m := utf8.DecodeRune(p[n:]); r {
case '\x1b':
return n
default:
n += m
e = ansi.Escape(r)
}
}
proc.ProcessANSI(e, a)
}
return n
}
// Processor receives decoded ANSI escape sequences and Unicode runes from
// Buffer.Process.
type Processor interface {
ProcessANSI(e ansi.Escape, a []byte)
}
var _ ansiWriter = &Buffer{}