-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstyle.go
161 lines (135 loc) · 5.02 KB
/
style.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
package anansi
import "github.com/jcorbin/anansi/ansi"
// Style allows styling of cell data during a drawing or rendering routine.
// Its eponymous method gets called for each cell as it is about to be
// rendered
//
// The Style method receives the point being rendered on screen or within a
// destination Grid. Its pr and pa arguments contain any prior rune and
// attribute data when drawing in a Grid, while the r and a arguments contain
// the source rune and attribute being drawn.
//
// Whatever rune and attribute values are returned by Style() will be the ones
// drawn/rendered.
//
// Style implementations are also called with all-zero argument values (i.e.
// an invalid ansi point) to probe any default rune/attr values. These default
// values are then used as fill values when rendering or drawing
type Style interface {
Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr)
}
// Styles combines zero or more styles into a non-nil Style; if given none, it
// returns a no-op Style; if given many, it returns a Style that calls each in
// turn.
func Styles(ss ...Style) Style {
var res styles
for _, s := range ss {
switch impl := s.(type) {
case _noopStyle:
continue
case styles:
res = append(res, impl...)
default:
res = append(res, s)
}
}
switch len(res) {
case 0:
return NoopStyle
case 1:
return res[0]
default:
return res
}
}
// StyleFunc is a convenience type alias for implementing Style.
type StyleFunc func(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr)
// Style calls the aliased function pointer
func (f StyleFunc) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
return f(p, pr, r, pa, a)
}
type _noopStyle struct{}
func (ns _noopStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
return r, 0
}
// NoopStyle is a no-op style, used as a zero fill by Styles.
var NoopStyle Style = _noopStyle{}
type styles []Style
func (ss styles) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
for _, s := range ss {
r, a = s.Style(p, pr, r, pa, a)
}
return r, a
}
// ZeroRuneStyle maps a fixed rune to 0. Useful for implementing transparency
// of rune values, e.g. space space characters or empty braille cells.
type ZeroRuneStyle rune
// TransparentBrailleRunes maps the empty braille rune to (U+2800) to 0.
var TransparentBrailleRunes = ZeroRuneStyle('\u2800')
// Style replaces the passed rune and attr with 0 if the rune equals the receiver.
func (es ZeroRuneStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if r == rune(es) {
r, a = 0, 0
}
return r, a
}
// FillRuneStyle maps 0 runes to a fixed rune value. Useful for normalizing
// transparent rune values when rendering a base grid.
type FillRuneStyle rune
// Style replaces the passed rune with the receiver if the passed rune is 0.
func (fs FillRuneStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if r == 0 {
r = rune(fs)
}
return r, a
}
// DefaultRuneStyle maps 0 runes to a fixed rune value, only when their
// coresponding SGRAttr value is non-zero.
type DefaultRuneStyle rune
// Style replaces the passed rune with the receiver if the passed rune is 0
// and the passed attr is not.
func (fs DefaultRuneStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if r == 0 && a != 0 {
r = rune(fs)
}
return r, a
}
// AttrStyle implements a Style that returns a fixed ansi attr for any non-zero runes.
type AttrStyle ansi.SGRAttr
// Style replaces the passed attr with the receiver if the passed rune is non-0.
func (as AttrStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if r != 0 {
a = ansi.SGRAttr(as)
}
return r, a
}
var (
// TransparentRunes is a style that stops 0 rune values from overwriting
// any prior rune values when drawing.
TransparentRunes Style = transparentRuneStyle{}
// TransparentAttrBG is a style that stops 0 background attribute from
// overwriting any prior attribute background value when drawing.
TransparentAttrBG Style = transparentAttrStyle(ansi.SGRAttrBGMask)
// TransparentAttrFG is a style that stops 0 foreground attribute from
// overwriting any prior attribute foreground value when drawing. This
// includes text attributes like bold and italics, not just foreground
// color.
TransparentAttrFG Style = transparentAttrStyle(ansi.SGRAttrFGMask | ansi.SGRAttrMask)
// TransparentAttrBGFG is a style that acts as both TransparentBG and
// TransparentAttrFG combined.
TransparentAttrBGFG Style = transparentAttrStyle(ansi.SGRAttrBGMask | ansi.SGRAttrFGMask | ansi.SGRAttrMask)
)
type transparentRuneStyle struct{}
type transparentAttrStyle ansi.SGRAttr
func (tr transparentRuneStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if r == 0 {
r = pr
}
return r, a
}
func (ta transparentAttrStyle) Style(p ansi.Point, pr, r rune, pa, a ansi.SGRAttr) (rune, ansi.SGRAttr) {
if a&ansi.SGRAttr(ta) == 0 {
a |= pa & ansi.SGRAttr(ta)
}
return r, a
}