main
Raw Download raw file
 1package ansi
 2
 3import (
 4	"bytes"
 5	"io"
 6	"unicode/utf8"
 7)
 8
 9type Writer struct {
10	Forward io.Writer
11
12	ansi       bool
13	ansiseq    bytes.Buffer
14	lastseq    bytes.Buffer
15	seqchanged bool
16	runeBuf    []byte
17}
18
19// Write is used to write content to the ANSI buffer.
20func (w *Writer) Write(b []byte) (int, error) {
21	for _, c := range string(b) {
22		if c == Marker {
23			// ANSI escape sequence
24			w.ansi = true
25			w.seqchanged = true
26			_, _ = w.ansiseq.WriteRune(c)
27		} else if w.ansi {
28			_, _ = w.ansiseq.WriteRune(c)
29			if IsTerminator(c) {
30				// ANSI sequence terminated
31				w.ansi = false
32
33				if bytes.HasSuffix(w.ansiseq.Bytes(), []byte("[0m")) {
34					// reset sequence
35					w.lastseq.Reset()
36					w.seqchanged = false
37				} else if c == 'm' {
38					// color code
39					_, _ = w.lastseq.Write(w.ansiseq.Bytes())
40				}
41
42				_, _ = w.ansiseq.WriteTo(w.Forward)
43			}
44		} else {
45			_, err := w.writeRune(c)
46			if err != nil {
47				return 0, err
48			}
49		}
50	}
51
52	return len(b), nil
53}
54
55func (w *Writer) writeRune(r rune) (int, error) {
56	if w.runeBuf == nil {
57		w.runeBuf = make([]byte, utf8.UTFMax)
58	}
59	n := utf8.EncodeRune(w.runeBuf, r)
60	return w.Forward.Write(w.runeBuf[:n])
61}
62
63func (w *Writer) LastSequence() string {
64	return w.lastseq.String()
65}
66
67func (w *Writer) ResetAnsi() {
68	if !w.seqchanged {
69		return
70	}
71	_, _ = w.Forward.Write([]byte("\x1b[0m"))
72}
73
74func (w *Writer) RestoreAnsi() {
75	_, _ = w.Forward.Write(w.lastseq.Bytes())
76}