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
|
package tui
import "io"
type StreamWriter struct {
w io.WriteCloser
app *App
col int
width int
esc escBuilder
caps Capabilities
nop bool
}
func (sw *StreamWriter) Write(p []byte) (int, error) {
return sw.w.Write(p)
}
func (sw *StreamWriter) Close() error {
return sw.w.Close()
}
func (sw *StreamWriter) WriteStyled(text string, style Style) (int, error) {
if sw.nop {
return len(text), nil
}
sw.esc.Reset()
sw.esc.SetStyle(style, sw.caps)
sw.esc.WriteString(text)
sw.esc.ResetStyle()
for _, r := range text {
if r == '\n' {
sw.col = 0
} else {
sw.col += RuneWidth(r)
if sw.width > 0 && sw.col >= sw.width {
sw.col = 0
}
}
}
return sw.w.Write(sw.esc.Bytes())
}
func (sw *StreamWriter) WriteGradient(text string, g Gradient, base ...Style) (int, error) {
if sw.nop {
return len(text), nil
}
var baseStyle Style
if len(base) > 0 {
baseStyle = base[0]
}
sw.esc.Reset()
for _, r := range text {
if r == '\n' {
sw.esc.ResetStyle()
sw.esc.WriteRune('\n')
sw.col = 0
continue
}
w := sw.width
if w < 1 {
w = 80
}
t := float64(sw.col) / float64(w-1)
if t > 1 {
t = 1
}
charStyle := baseStyle
charStyle.Fg = g.At(t)
sw.esc.SetStyle(charStyle, sw.caps)
sw.esc.WriteRune(r)
sw.col += RuneWidth(r)
if sw.width > 0 && sw.col >= sw.width {
sw.col = 0
}
}
sw.esc.ResetStyle()
return sw.w.Write(sw.esc.Bytes())
}
func (sw *StreamWriter) WriteElement(v Viewable) {
if sw.nop || sw.app == nil {
return
}
sw.app.QueueUpdate(func() {
sw.app.PrintAboveElement(v)
})
sw.col = 0
}
|