doing 2.0.20 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/doing.rdoc +1 -1
- data/lib/doing/version.rb +1 -1
- data/lib/helpers/fzf/.goreleaser.yml +119 -0
- data/lib/helpers/fzf/.rubocop.yml +28 -0
- data/lib/helpers/fzf/ADVANCED.md +565 -0
- data/lib/helpers/fzf/BUILD.md +49 -0
- data/lib/helpers/fzf/CHANGELOG.md +1193 -0
- data/lib/helpers/fzf/Dockerfile +11 -0
- data/lib/helpers/fzf/LICENSE +21 -0
- data/lib/helpers/fzf/Makefile +166 -0
- data/lib/helpers/fzf/README-VIM.md +486 -0
- data/lib/helpers/fzf/README.md +712 -0
- data/lib/helpers/fzf/bin/fzf-tmux +233 -0
- data/lib/helpers/fzf/doc/fzf.txt +512 -0
- data/lib/helpers/fzf/go.mod +17 -0
- data/lib/helpers/fzf/go.sum +31 -0
- data/lib/helpers/fzf/install +382 -0
- data/lib/helpers/fzf/install.ps1 +65 -0
- data/lib/helpers/fzf/main.go +14 -0
- data/lib/helpers/fzf/man/man1/fzf-tmux.1 +68 -0
- data/lib/helpers/fzf/man/man1/fzf.1 +1001 -0
- data/lib/helpers/fzf/plugin/fzf.vim +1048 -0
- data/lib/helpers/fzf/shell/completion.bash +381 -0
- data/lib/helpers/fzf/shell/completion.zsh +329 -0
- data/lib/helpers/fzf/shell/key-bindings.bash +96 -0
- data/lib/helpers/fzf/shell/key-bindings.fish +172 -0
- data/lib/helpers/fzf/shell/key-bindings.zsh +114 -0
- data/lib/helpers/fzf/src/LICENSE +21 -0
- data/lib/helpers/fzf/src/algo/algo.go +884 -0
- data/lib/helpers/fzf/src/algo/algo_test.go +197 -0
- data/lib/helpers/fzf/src/algo/normalize.go +492 -0
- data/lib/helpers/fzf/src/ansi.go +409 -0
- data/lib/helpers/fzf/src/ansi_test.go +427 -0
- data/lib/helpers/fzf/src/cache.go +81 -0
- data/lib/helpers/fzf/src/cache_test.go +39 -0
- data/lib/helpers/fzf/src/chunklist.go +89 -0
- data/lib/helpers/fzf/src/chunklist_test.go +80 -0
- data/lib/helpers/fzf/src/constants.go +85 -0
- data/lib/helpers/fzf/src/core.go +351 -0
- data/lib/helpers/fzf/src/history.go +96 -0
- data/lib/helpers/fzf/src/history_test.go +68 -0
- data/lib/helpers/fzf/src/item.go +44 -0
- data/lib/helpers/fzf/src/item_test.go +23 -0
- data/lib/helpers/fzf/src/matcher.go +235 -0
- data/lib/helpers/fzf/src/merger.go +120 -0
- data/lib/helpers/fzf/src/merger_test.go +88 -0
- data/lib/helpers/fzf/src/options.go +1691 -0
- data/lib/helpers/fzf/src/options_test.go +457 -0
- data/lib/helpers/fzf/src/pattern.go +425 -0
- data/lib/helpers/fzf/src/pattern_test.go +209 -0
- data/lib/helpers/fzf/src/protector/protector.go +8 -0
- data/lib/helpers/fzf/src/protector/protector_openbsd.go +10 -0
- data/lib/helpers/fzf/src/reader.go +201 -0
- data/lib/helpers/fzf/src/reader_test.go +63 -0
- data/lib/helpers/fzf/src/result.go +243 -0
- data/lib/helpers/fzf/src/result_others.go +16 -0
- data/lib/helpers/fzf/src/result_test.go +159 -0
- data/lib/helpers/fzf/src/result_x86.go +16 -0
- data/lib/helpers/fzf/src/terminal.go +2832 -0
- data/lib/helpers/fzf/src/terminal_test.go +638 -0
- data/lib/helpers/fzf/src/terminal_unix.go +26 -0
- data/lib/helpers/fzf/src/terminal_windows.go +45 -0
- data/lib/helpers/fzf/src/tokenizer.go +253 -0
- data/lib/helpers/fzf/src/tokenizer_test.go +112 -0
- data/lib/helpers/fzf/src/tui/dummy.go +46 -0
- data/lib/helpers/fzf/src/tui/light.go +987 -0
- data/lib/helpers/fzf/src/tui/light_unix.go +110 -0
- data/lib/helpers/fzf/src/tui/light_windows.go +145 -0
- data/lib/helpers/fzf/src/tui/tcell.go +721 -0
- data/lib/helpers/fzf/src/tui/tcell_test.go +392 -0
- data/lib/helpers/fzf/src/tui/ttyname_unix.go +47 -0
- data/lib/helpers/fzf/src/tui/ttyname_windows.go +14 -0
- data/lib/helpers/fzf/src/tui/tui.go +625 -0
- data/lib/helpers/fzf/src/tui/tui_test.go +20 -0
- data/lib/helpers/fzf/src/util/atomicbool.go +34 -0
- data/lib/helpers/fzf/src/util/atomicbool_test.go +17 -0
- data/lib/helpers/fzf/src/util/chars.go +198 -0
- data/lib/helpers/fzf/src/util/chars_test.go +46 -0
- data/lib/helpers/fzf/src/util/eventbox.go +96 -0
- data/lib/helpers/fzf/src/util/eventbox_test.go +61 -0
- data/lib/helpers/fzf/src/util/slab.go +12 -0
- data/lib/helpers/fzf/src/util/util.go +138 -0
- data/lib/helpers/fzf/src/util/util_test.go +40 -0
- data/lib/helpers/fzf/src/util/util_unix.go +47 -0
- data/lib/helpers/fzf/src/util/util_windows.go +83 -0
- data/lib/helpers/fzf/test/fzf.vader +175 -0
- data/lib/helpers/fzf/test/test_go.rb +2626 -0
- data/lib/helpers/fzf/uninstall +117 -0
- metadata +87 -1
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
package tui
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"os"
|
|
6
|
+
"strconv"
|
|
7
|
+
"time"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Types of user action
|
|
11
|
+
type EventType int
|
|
12
|
+
|
|
13
|
+
const (
|
|
14
|
+
Rune EventType = iota
|
|
15
|
+
|
|
16
|
+
CtrlA
|
|
17
|
+
CtrlB
|
|
18
|
+
CtrlC
|
|
19
|
+
CtrlD
|
|
20
|
+
CtrlE
|
|
21
|
+
CtrlF
|
|
22
|
+
CtrlG
|
|
23
|
+
CtrlH
|
|
24
|
+
Tab
|
|
25
|
+
CtrlJ
|
|
26
|
+
CtrlK
|
|
27
|
+
CtrlL
|
|
28
|
+
CtrlM
|
|
29
|
+
CtrlN
|
|
30
|
+
CtrlO
|
|
31
|
+
CtrlP
|
|
32
|
+
CtrlQ
|
|
33
|
+
CtrlR
|
|
34
|
+
CtrlS
|
|
35
|
+
CtrlT
|
|
36
|
+
CtrlU
|
|
37
|
+
CtrlV
|
|
38
|
+
CtrlW
|
|
39
|
+
CtrlX
|
|
40
|
+
CtrlY
|
|
41
|
+
CtrlZ
|
|
42
|
+
ESC
|
|
43
|
+
CtrlSpace
|
|
44
|
+
|
|
45
|
+
// https://apple.stackexchange.com/questions/24261/how-do-i-send-c-that-is-control-slash-to-the-terminal
|
|
46
|
+
CtrlBackSlash
|
|
47
|
+
CtrlRightBracket
|
|
48
|
+
CtrlCaret
|
|
49
|
+
CtrlSlash
|
|
50
|
+
|
|
51
|
+
Invalid
|
|
52
|
+
Resize
|
|
53
|
+
Mouse
|
|
54
|
+
DoubleClick
|
|
55
|
+
LeftClick
|
|
56
|
+
RightClick
|
|
57
|
+
|
|
58
|
+
BTab
|
|
59
|
+
BSpace
|
|
60
|
+
|
|
61
|
+
Del
|
|
62
|
+
PgUp
|
|
63
|
+
PgDn
|
|
64
|
+
|
|
65
|
+
Up
|
|
66
|
+
Down
|
|
67
|
+
Left
|
|
68
|
+
Right
|
|
69
|
+
Home
|
|
70
|
+
End
|
|
71
|
+
Insert
|
|
72
|
+
|
|
73
|
+
SUp
|
|
74
|
+
SDown
|
|
75
|
+
SLeft
|
|
76
|
+
SRight
|
|
77
|
+
|
|
78
|
+
F1
|
|
79
|
+
F2
|
|
80
|
+
F3
|
|
81
|
+
F4
|
|
82
|
+
F5
|
|
83
|
+
F6
|
|
84
|
+
F7
|
|
85
|
+
F8
|
|
86
|
+
F9
|
|
87
|
+
F10
|
|
88
|
+
F11
|
|
89
|
+
F12
|
|
90
|
+
|
|
91
|
+
Change
|
|
92
|
+
BackwardEOF
|
|
93
|
+
|
|
94
|
+
AltBS
|
|
95
|
+
|
|
96
|
+
AltUp
|
|
97
|
+
AltDown
|
|
98
|
+
AltLeft
|
|
99
|
+
AltRight
|
|
100
|
+
|
|
101
|
+
AltSUp
|
|
102
|
+
AltSDown
|
|
103
|
+
AltSLeft
|
|
104
|
+
AltSRight
|
|
105
|
+
|
|
106
|
+
Alt
|
|
107
|
+
CtrlAlt
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
func (t EventType) AsEvent() Event {
|
|
111
|
+
return Event{t, 0, nil}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
func (t EventType) Int() int {
|
|
115
|
+
return int(t)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func (t EventType) Byte() byte {
|
|
119
|
+
return byte(t)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func (e Event) Comparable() Event {
|
|
123
|
+
// Ignore MouseEvent pointer
|
|
124
|
+
return Event{e.Type, e.Char, nil}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
func Key(r rune) Event {
|
|
128
|
+
return Event{Rune, r, nil}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func AltKey(r rune) Event {
|
|
132
|
+
return Event{Alt, r, nil}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func CtrlAltKey(r rune) Event {
|
|
136
|
+
return Event{CtrlAlt, r, nil}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const (
|
|
140
|
+
doubleClickDuration = 500 * time.Millisecond
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
type Color int32
|
|
144
|
+
|
|
145
|
+
func (c Color) IsDefault() bool {
|
|
146
|
+
return c == colDefault
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
func (c Color) is24() bool {
|
|
150
|
+
return c > 0 && (c&(1<<24)) > 0
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
type ColorAttr struct {
|
|
154
|
+
Color Color
|
|
155
|
+
Attr Attr
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
func NewColorAttr() ColorAttr {
|
|
159
|
+
return ColorAttr{Color: colUndefined, Attr: AttrUndefined}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const (
|
|
163
|
+
colUndefined Color = -2
|
|
164
|
+
colDefault Color = -1
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
const (
|
|
168
|
+
colBlack Color = iota
|
|
169
|
+
colRed
|
|
170
|
+
colGreen
|
|
171
|
+
colYellow
|
|
172
|
+
colBlue
|
|
173
|
+
colMagenta
|
|
174
|
+
colCyan
|
|
175
|
+
colWhite
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
type FillReturn int
|
|
179
|
+
|
|
180
|
+
const (
|
|
181
|
+
FillContinue FillReturn = iota
|
|
182
|
+
FillNextLine
|
|
183
|
+
FillSuspend
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
type ColorPair struct {
|
|
187
|
+
fg Color
|
|
188
|
+
bg Color
|
|
189
|
+
attr Attr
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
func HexToColor(rrggbb string) Color {
|
|
193
|
+
r, _ := strconv.ParseInt(rrggbb[1:3], 16, 0)
|
|
194
|
+
g, _ := strconv.ParseInt(rrggbb[3:5], 16, 0)
|
|
195
|
+
b, _ := strconv.ParseInt(rrggbb[5:7], 16, 0)
|
|
196
|
+
return Color((1 << 24) + (r << 16) + (g << 8) + b)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
func NewColorPair(fg Color, bg Color, attr Attr) ColorPair {
|
|
200
|
+
return ColorPair{fg, bg, attr}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
func (p ColorPair) Fg() Color {
|
|
204
|
+
return p.fg
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
func (p ColorPair) Bg() Color {
|
|
208
|
+
return p.bg
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
func (p ColorPair) Attr() Attr {
|
|
212
|
+
return p.attr
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
func (p ColorPair) HasBg() bool {
|
|
216
|
+
return p.attr&Reverse == 0 && p.bg != colDefault ||
|
|
217
|
+
p.attr&Reverse > 0 && p.fg != colDefault
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
func (p ColorPair) merge(other ColorPair, except Color) ColorPair {
|
|
221
|
+
dup := p
|
|
222
|
+
dup.attr = dup.attr.Merge(other.attr)
|
|
223
|
+
if other.fg != except {
|
|
224
|
+
dup.fg = other.fg
|
|
225
|
+
}
|
|
226
|
+
if other.bg != except {
|
|
227
|
+
dup.bg = other.bg
|
|
228
|
+
}
|
|
229
|
+
return dup
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
func (p ColorPair) WithAttr(attr Attr) ColorPair {
|
|
233
|
+
dup := p
|
|
234
|
+
dup.attr = dup.attr.Merge(attr)
|
|
235
|
+
return dup
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
func (p ColorPair) MergeAttr(other ColorPair) ColorPair {
|
|
239
|
+
return p.WithAttr(other.attr)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
func (p ColorPair) Merge(other ColorPair) ColorPair {
|
|
243
|
+
return p.merge(other, colUndefined)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
func (p ColorPair) MergeNonDefault(other ColorPair) ColorPair {
|
|
247
|
+
return p.merge(other, colDefault)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
type ColorTheme struct {
|
|
251
|
+
Colored bool
|
|
252
|
+
Input ColorAttr
|
|
253
|
+
Disabled ColorAttr
|
|
254
|
+
Fg ColorAttr
|
|
255
|
+
Bg ColorAttr
|
|
256
|
+
PreviewFg ColorAttr
|
|
257
|
+
PreviewBg ColorAttr
|
|
258
|
+
DarkBg ColorAttr
|
|
259
|
+
Gutter ColorAttr
|
|
260
|
+
Prompt ColorAttr
|
|
261
|
+
Match ColorAttr
|
|
262
|
+
Current ColorAttr
|
|
263
|
+
CurrentMatch ColorAttr
|
|
264
|
+
Spinner ColorAttr
|
|
265
|
+
Info ColorAttr
|
|
266
|
+
Cursor ColorAttr
|
|
267
|
+
Selected ColorAttr
|
|
268
|
+
Header ColorAttr
|
|
269
|
+
Border ColorAttr
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type Event struct {
|
|
273
|
+
Type EventType
|
|
274
|
+
Char rune
|
|
275
|
+
MouseEvent *MouseEvent
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
type MouseEvent struct {
|
|
279
|
+
Y int
|
|
280
|
+
X int
|
|
281
|
+
S int
|
|
282
|
+
Left bool
|
|
283
|
+
Down bool
|
|
284
|
+
Double bool
|
|
285
|
+
Mod bool
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
type BorderShape int
|
|
289
|
+
|
|
290
|
+
const (
|
|
291
|
+
BorderNone BorderShape = iota
|
|
292
|
+
BorderRounded
|
|
293
|
+
BorderSharp
|
|
294
|
+
BorderHorizontal
|
|
295
|
+
BorderVertical
|
|
296
|
+
BorderTop
|
|
297
|
+
BorderBottom
|
|
298
|
+
BorderLeft
|
|
299
|
+
BorderRight
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
type BorderStyle struct {
|
|
303
|
+
shape BorderShape
|
|
304
|
+
horizontal rune
|
|
305
|
+
vertical rune
|
|
306
|
+
topLeft rune
|
|
307
|
+
topRight rune
|
|
308
|
+
bottomLeft rune
|
|
309
|
+
bottomRight rune
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
type BorderCharacter int
|
|
313
|
+
|
|
314
|
+
func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
|
|
315
|
+
if unicode {
|
|
316
|
+
if shape == BorderRounded {
|
|
317
|
+
return BorderStyle{
|
|
318
|
+
shape: shape,
|
|
319
|
+
horizontal: '─',
|
|
320
|
+
vertical: '│',
|
|
321
|
+
topLeft: '╭',
|
|
322
|
+
topRight: '╮',
|
|
323
|
+
bottomLeft: '╰',
|
|
324
|
+
bottomRight: '╯',
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return BorderStyle{
|
|
328
|
+
shape: shape,
|
|
329
|
+
horizontal: '─',
|
|
330
|
+
vertical: '│',
|
|
331
|
+
topLeft: '┌',
|
|
332
|
+
topRight: '┐',
|
|
333
|
+
bottomLeft: '└',
|
|
334
|
+
bottomRight: '┘',
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return BorderStyle{
|
|
338
|
+
shape: shape,
|
|
339
|
+
horizontal: '-',
|
|
340
|
+
vertical: '|',
|
|
341
|
+
topLeft: '+',
|
|
342
|
+
topRight: '+',
|
|
343
|
+
bottomLeft: '+',
|
|
344
|
+
bottomRight: '+',
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
func MakeTransparentBorder() BorderStyle {
|
|
349
|
+
return BorderStyle{
|
|
350
|
+
shape: BorderRounded,
|
|
351
|
+
horizontal: ' ',
|
|
352
|
+
vertical: ' ',
|
|
353
|
+
topLeft: ' ',
|
|
354
|
+
topRight: ' ',
|
|
355
|
+
bottomLeft: ' ',
|
|
356
|
+
bottomRight: ' '}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
type Renderer interface {
|
|
360
|
+
Init()
|
|
361
|
+
Pause(clear bool)
|
|
362
|
+
Resume(clear bool, sigcont bool)
|
|
363
|
+
Clear()
|
|
364
|
+
RefreshWindows(windows []Window)
|
|
365
|
+
Refresh()
|
|
366
|
+
Close()
|
|
367
|
+
|
|
368
|
+
GetChar() Event
|
|
369
|
+
|
|
370
|
+
MaxX() int
|
|
371
|
+
MaxY() int
|
|
372
|
+
|
|
373
|
+
NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
type Window interface {
|
|
377
|
+
Top() int
|
|
378
|
+
Left() int
|
|
379
|
+
Width() int
|
|
380
|
+
Height() int
|
|
381
|
+
|
|
382
|
+
Refresh()
|
|
383
|
+
FinishFill()
|
|
384
|
+
Close()
|
|
385
|
+
|
|
386
|
+
X() int
|
|
387
|
+
Y() int
|
|
388
|
+
Enclose(y int, x int) bool
|
|
389
|
+
|
|
390
|
+
Move(y int, x int)
|
|
391
|
+
MoveAndClear(y int, x int)
|
|
392
|
+
Print(text string)
|
|
393
|
+
CPrint(color ColorPair, text string)
|
|
394
|
+
Fill(text string) FillReturn
|
|
395
|
+
CFill(fg Color, bg Color, attr Attr, text string) FillReturn
|
|
396
|
+
Erase()
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
type FullscreenRenderer struct {
|
|
400
|
+
theme *ColorTheme
|
|
401
|
+
mouse bool
|
|
402
|
+
forceBlack bool
|
|
403
|
+
prevDownTime time.Time
|
|
404
|
+
clickY []int
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Renderer {
|
|
408
|
+
r := &FullscreenRenderer{
|
|
409
|
+
theme: theme,
|
|
410
|
+
mouse: mouse,
|
|
411
|
+
forceBlack: forceBlack,
|
|
412
|
+
prevDownTime: time.Unix(0, 0),
|
|
413
|
+
clickY: []int{}}
|
|
414
|
+
return r
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
var (
|
|
418
|
+
Default16 *ColorTheme
|
|
419
|
+
Dark256 *ColorTheme
|
|
420
|
+
Light256 *ColorTheme
|
|
421
|
+
|
|
422
|
+
ColPrompt ColorPair
|
|
423
|
+
ColNormal ColorPair
|
|
424
|
+
ColInput ColorPair
|
|
425
|
+
ColDisabled ColorPair
|
|
426
|
+
ColMatch ColorPair
|
|
427
|
+
ColCursor ColorPair
|
|
428
|
+
ColCursorEmpty ColorPair
|
|
429
|
+
ColSelected ColorPair
|
|
430
|
+
ColCurrent ColorPair
|
|
431
|
+
ColCurrentMatch ColorPair
|
|
432
|
+
ColCurrentCursor ColorPair
|
|
433
|
+
ColCurrentCursorEmpty ColorPair
|
|
434
|
+
ColCurrentSelected ColorPair
|
|
435
|
+
ColCurrentSelectedEmpty ColorPair
|
|
436
|
+
ColSpinner ColorPair
|
|
437
|
+
ColInfo ColorPair
|
|
438
|
+
ColHeader ColorPair
|
|
439
|
+
ColBorder ColorPair
|
|
440
|
+
ColPreview ColorPair
|
|
441
|
+
ColPreviewBorder ColorPair
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
func EmptyTheme() *ColorTheme {
|
|
445
|
+
return &ColorTheme{
|
|
446
|
+
Colored: true,
|
|
447
|
+
Input: ColorAttr{colUndefined, AttrUndefined},
|
|
448
|
+
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
449
|
+
Fg: ColorAttr{colUndefined, AttrUndefined},
|
|
450
|
+
Bg: ColorAttr{colUndefined, AttrUndefined},
|
|
451
|
+
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
452
|
+
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
453
|
+
DarkBg: ColorAttr{colUndefined, AttrUndefined},
|
|
454
|
+
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
455
|
+
Prompt: ColorAttr{colUndefined, AttrUndefined},
|
|
456
|
+
Match: ColorAttr{colUndefined, AttrUndefined},
|
|
457
|
+
Current: ColorAttr{colUndefined, AttrUndefined},
|
|
458
|
+
CurrentMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
459
|
+
Spinner: ColorAttr{colUndefined, AttrUndefined},
|
|
460
|
+
Info: ColorAttr{colUndefined, AttrUndefined},
|
|
461
|
+
Cursor: ColorAttr{colUndefined, AttrUndefined},
|
|
462
|
+
Selected: ColorAttr{colUndefined, AttrUndefined},
|
|
463
|
+
Header: ColorAttr{colUndefined, AttrUndefined},
|
|
464
|
+
Border: ColorAttr{colUndefined, AttrUndefined}}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
func NoColorTheme() *ColorTheme {
|
|
468
|
+
return &ColorTheme{
|
|
469
|
+
Colored: false,
|
|
470
|
+
Input: ColorAttr{colDefault, AttrRegular},
|
|
471
|
+
Disabled: ColorAttr{colDefault, AttrRegular},
|
|
472
|
+
Fg: ColorAttr{colDefault, AttrRegular},
|
|
473
|
+
Bg: ColorAttr{colDefault, AttrRegular},
|
|
474
|
+
PreviewFg: ColorAttr{colDefault, AttrRegular},
|
|
475
|
+
PreviewBg: ColorAttr{colDefault, AttrRegular},
|
|
476
|
+
DarkBg: ColorAttr{colDefault, AttrRegular},
|
|
477
|
+
Gutter: ColorAttr{colDefault, AttrRegular},
|
|
478
|
+
Prompt: ColorAttr{colDefault, AttrRegular},
|
|
479
|
+
Match: ColorAttr{colDefault, Underline},
|
|
480
|
+
Current: ColorAttr{colDefault, Reverse},
|
|
481
|
+
CurrentMatch: ColorAttr{colDefault, Reverse | Underline},
|
|
482
|
+
Spinner: ColorAttr{colDefault, AttrRegular},
|
|
483
|
+
Info: ColorAttr{colDefault, AttrRegular},
|
|
484
|
+
Cursor: ColorAttr{colDefault, AttrRegular},
|
|
485
|
+
Selected: ColorAttr{colDefault, AttrRegular},
|
|
486
|
+
Header: ColorAttr{colDefault, AttrRegular},
|
|
487
|
+
Border: ColorAttr{colDefault, AttrRegular}}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
func errorExit(message string) {
|
|
491
|
+
fmt.Fprintln(os.Stderr, message)
|
|
492
|
+
os.Exit(2)
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
func init() {
|
|
496
|
+
Default16 = &ColorTheme{
|
|
497
|
+
Colored: true,
|
|
498
|
+
Input: ColorAttr{colDefault, AttrUndefined},
|
|
499
|
+
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
500
|
+
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
501
|
+
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
502
|
+
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
503
|
+
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
504
|
+
DarkBg: ColorAttr{colBlack, AttrUndefined},
|
|
505
|
+
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
506
|
+
Prompt: ColorAttr{colBlue, AttrUndefined},
|
|
507
|
+
Match: ColorAttr{colGreen, AttrUndefined},
|
|
508
|
+
Current: ColorAttr{colYellow, AttrUndefined},
|
|
509
|
+
CurrentMatch: ColorAttr{colGreen, AttrUndefined},
|
|
510
|
+
Spinner: ColorAttr{colGreen, AttrUndefined},
|
|
511
|
+
Info: ColorAttr{colWhite, AttrUndefined},
|
|
512
|
+
Cursor: ColorAttr{colRed, AttrUndefined},
|
|
513
|
+
Selected: ColorAttr{colMagenta, AttrUndefined},
|
|
514
|
+
Header: ColorAttr{colCyan, AttrUndefined},
|
|
515
|
+
Border: ColorAttr{colBlack, AttrUndefined}}
|
|
516
|
+
Dark256 = &ColorTheme{
|
|
517
|
+
Colored: true,
|
|
518
|
+
Input: ColorAttr{colDefault, AttrUndefined},
|
|
519
|
+
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
520
|
+
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
521
|
+
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
522
|
+
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
523
|
+
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
524
|
+
DarkBg: ColorAttr{236, AttrUndefined},
|
|
525
|
+
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
526
|
+
Prompt: ColorAttr{110, AttrUndefined},
|
|
527
|
+
Match: ColorAttr{108, AttrUndefined},
|
|
528
|
+
Current: ColorAttr{254, AttrUndefined},
|
|
529
|
+
CurrentMatch: ColorAttr{151, AttrUndefined},
|
|
530
|
+
Spinner: ColorAttr{148, AttrUndefined},
|
|
531
|
+
Info: ColorAttr{144, AttrUndefined},
|
|
532
|
+
Cursor: ColorAttr{161, AttrUndefined},
|
|
533
|
+
Selected: ColorAttr{168, AttrUndefined},
|
|
534
|
+
Header: ColorAttr{109, AttrUndefined},
|
|
535
|
+
Border: ColorAttr{59, AttrUndefined}}
|
|
536
|
+
Light256 = &ColorTheme{
|
|
537
|
+
Colored: true,
|
|
538
|
+
Input: ColorAttr{colDefault, AttrUndefined},
|
|
539
|
+
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
540
|
+
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
541
|
+
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
542
|
+
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
543
|
+
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
544
|
+
DarkBg: ColorAttr{251, AttrUndefined},
|
|
545
|
+
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
546
|
+
Prompt: ColorAttr{25, AttrUndefined},
|
|
547
|
+
Match: ColorAttr{66, AttrUndefined},
|
|
548
|
+
Current: ColorAttr{237, AttrUndefined},
|
|
549
|
+
CurrentMatch: ColorAttr{23, AttrUndefined},
|
|
550
|
+
Spinner: ColorAttr{65, AttrUndefined},
|
|
551
|
+
Info: ColorAttr{101, AttrUndefined},
|
|
552
|
+
Cursor: ColorAttr{161, AttrUndefined},
|
|
553
|
+
Selected: ColorAttr{168, AttrUndefined},
|
|
554
|
+
Header: ColorAttr{31, AttrUndefined},
|
|
555
|
+
Border: ColorAttr{145, AttrUndefined}}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) {
|
|
559
|
+
if forceBlack {
|
|
560
|
+
theme.Bg = ColorAttr{colBlack, AttrUndefined}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
o := func(a ColorAttr, b ColorAttr) ColorAttr {
|
|
564
|
+
c := a
|
|
565
|
+
if b.Color != colUndefined {
|
|
566
|
+
c.Color = b.Color
|
|
567
|
+
}
|
|
568
|
+
if b.Attr != AttrUndefined {
|
|
569
|
+
c.Attr = b.Attr
|
|
570
|
+
}
|
|
571
|
+
return c
|
|
572
|
+
}
|
|
573
|
+
theme.Input = o(baseTheme.Input, theme.Input)
|
|
574
|
+
theme.Disabled = o(theme.Input, o(baseTheme.Disabled, theme.Disabled))
|
|
575
|
+
theme.Fg = o(baseTheme.Fg, theme.Fg)
|
|
576
|
+
theme.Bg = o(baseTheme.Bg, theme.Bg)
|
|
577
|
+
theme.PreviewFg = o(theme.Fg, o(baseTheme.PreviewFg, theme.PreviewFg))
|
|
578
|
+
theme.PreviewBg = o(theme.Bg, o(baseTheme.PreviewBg, theme.PreviewBg))
|
|
579
|
+
theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
|
|
580
|
+
theme.Gutter = o(theme.DarkBg, o(baseTheme.Gutter, theme.Gutter))
|
|
581
|
+
theme.Prompt = o(baseTheme.Prompt, theme.Prompt)
|
|
582
|
+
theme.Match = o(baseTheme.Match, theme.Match)
|
|
583
|
+
theme.Current = o(baseTheme.Current, theme.Current)
|
|
584
|
+
theme.CurrentMatch = o(baseTheme.CurrentMatch, theme.CurrentMatch)
|
|
585
|
+
theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
|
|
586
|
+
theme.Info = o(baseTheme.Info, theme.Info)
|
|
587
|
+
theme.Cursor = o(baseTheme.Cursor, theme.Cursor)
|
|
588
|
+
theme.Selected = o(baseTheme.Selected, theme.Selected)
|
|
589
|
+
theme.Header = o(baseTheme.Header, theme.Header)
|
|
590
|
+
theme.Border = o(baseTheme.Border, theme.Border)
|
|
591
|
+
|
|
592
|
+
initPalette(theme)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
func initPalette(theme *ColorTheme) {
|
|
596
|
+
pair := func(fg, bg ColorAttr) ColorPair {
|
|
597
|
+
if fg.Color == colDefault && (fg.Attr&Reverse) > 0 {
|
|
598
|
+
bg.Color = colDefault
|
|
599
|
+
}
|
|
600
|
+
return ColorPair{fg.Color, bg.Color, fg.Attr}
|
|
601
|
+
}
|
|
602
|
+
blank := theme.Fg
|
|
603
|
+
blank.Attr = AttrRegular
|
|
604
|
+
|
|
605
|
+
ColPrompt = pair(theme.Prompt, theme.Bg)
|
|
606
|
+
ColNormal = pair(theme.Fg, theme.Bg)
|
|
607
|
+
ColInput = pair(theme.Input, theme.Bg)
|
|
608
|
+
ColDisabled = pair(theme.Disabled, theme.Bg)
|
|
609
|
+
ColMatch = pair(theme.Match, theme.Bg)
|
|
610
|
+
ColCursor = pair(theme.Cursor, theme.Gutter)
|
|
611
|
+
ColCursorEmpty = pair(blank, theme.Gutter)
|
|
612
|
+
ColSelected = pair(theme.Selected, theme.Gutter)
|
|
613
|
+
ColCurrent = pair(theme.Current, theme.DarkBg)
|
|
614
|
+
ColCurrentMatch = pair(theme.CurrentMatch, theme.DarkBg)
|
|
615
|
+
ColCurrentCursor = pair(theme.Cursor, theme.DarkBg)
|
|
616
|
+
ColCurrentCursorEmpty = pair(blank, theme.DarkBg)
|
|
617
|
+
ColCurrentSelected = pair(theme.Selected, theme.DarkBg)
|
|
618
|
+
ColCurrentSelectedEmpty = pair(blank, theme.DarkBg)
|
|
619
|
+
ColSpinner = pair(theme.Spinner, theme.Bg)
|
|
620
|
+
ColInfo = pair(theme.Info, theme.Bg)
|
|
621
|
+
ColHeader = pair(theme.Header, theme.Bg)
|
|
622
|
+
ColBorder = pair(theme.Border, theme.Bg)
|
|
623
|
+
ColPreview = pair(theme.PreviewFg, theme.PreviewBg)
|
|
624
|
+
ColPreviewBorder = pair(theme.Border, theme.PreviewBg)
|
|
625
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package tui
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
func TestHexToColor(t *testing.T) {
|
|
6
|
+
assert := func(expr string, r, g, b int) {
|
|
7
|
+
color := HexToColor(expr)
|
|
8
|
+
if !color.is24() ||
|
|
9
|
+
int((color>>16)&0xff) != r ||
|
|
10
|
+
int((color>>8)&0xff) != g ||
|
|
11
|
+
int((color)&0xff) != b {
|
|
12
|
+
t.Fail()
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
assert("#ff0000", 255, 0, 0)
|
|
17
|
+
assert("#010203", 1, 2, 3)
|
|
18
|
+
assert("#102030", 16, 32, 48)
|
|
19
|
+
assert("#ffffff", 255, 255, 255)
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package util
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"sync/atomic"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
func convertBoolToInt32(b bool) int32 {
|
|
8
|
+
if b {
|
|
9
|
+
return 1
|
|
10
|
+
}
|
|
11
|
+
return 0
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// AtomicBool is a boxed-class that provides synchronized access to the
|
|
15
|
+
// underlying boolean value
|
|
16
|
+
type AtomicBool struct {
|
|
17
|
+
state int32 // "1" is true, "0" is false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// NewAtomicBool returns a new AtomicBool
|
|
21
|
+
func NewAtomicBool(initialState bool) *AtomicBool {
|
|
22
|
+
return &AtomicBool{state: convertBoolToInt32(initialState)}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Get returns the current boolean value synchronously
|
|
26
|
+
func (a *AtomicBool) Get() bool {
|
|
27
|
+
return atomic.LoadInt32(&a.state) == 1
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Set updates the boolean value synchronously
|
|
31
|
+
func (a *AtomicBool) Set(newState bool) bool {
|
|
32
|
+
atomic.StoreInt32(&a.state, convertBoolToInt32(newState))
|
|
33
|
+
return newState
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package util
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
func TestAtomicBool(t *testing.T) {
|
|
6
|
+
if !NewAtomicBool(true).Get() || NewAtomicBool(false).Get() {
|
|
7
|
+
t.Error("Invalid initial value")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
ab := NewAtomicBool(true)
|
|
11
|
+
if ab.Set(false) {
|
|
12
|
+
t.Error("Invalid return value")
|
|
13
|
+
}
|
|
14
|
+
if ab.Get() {
|
|
15
|
+
t.Error("Invalid state")
|
|
16
|
+
}
|
|
17
|
+
}
|