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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/doing.rdoc +1 -1
  6. data/lib/doing/version.rb +1 -1
  7. data/lib/helpers/fzf/.goreleaser.yml +119 -0
  8. data/lib/helpers/fzf/.rubocop.yml +28 -0
  9. data/lib/helpers/fzf/ADVANCED.md +565 -0
  10. data/lib/helpers/fzf/BUILD.md +49 -0
  11. data/lib/helpers/fzf/CHANGELOG.md +1193 -0
  12. data/lib/helpers/fzf/Dockerfile +11 -0
  13. data/lib/helpers/fzf/LICENSE +21 -0
  14. data/lib/helpers/fzf/Makefile +166 -0
  15. data/lib/helpers/fzf/README-VIM.md +486 -0
  16. data/lib/helpers/fzf/README.md +712 -0
  17. data/lib/helpers/fzf/bin/fzf-tmux +233 -0
  18. data/lib/helpers/fzf/doc/fzf.txt +512 -0
  19. data/lib/helpers/fzf/go.mod +17 -0
  20. data/lib/helpers/fzf/go.sum +31 -0
  21. data/lib/helpers/fzf/install +382 -0
  22. data/lib/helpers/fzf/install.ps1 +65 -0
  23. data/lib/helpers/fzf/main.go +14 -0
  24. data/lib/helpers/fzf/man/man1/fzf-tmux.1 +68 -0
  25. data/lib/helpers/fzf/man/man1/fzf.1 +1001 -0
  26. data/lib/helpers/fzf/plugin/fzf.vim +1048 -0
  27. data/lib/helpers/fzf/shell/completion.bash +381 -0
  28. data/lib/helpers/fzf/shell/completion.zsh +329 -0
  29. data/lib/helpers/fzf/shell/key-bindings.bash +96 -0
  30. data/lib/helpers/fzf/shell/key-bindings.fish +172 -0
  31. data/lib/helpers/fzf/shell/key-bindings.zsh +114 -0
  32. data/lib/helpers/fzf/src/LICENSE +21 -0
  33. data/lib/helpers/fzf/src/algo/algo.go +884 -0
  34. data/lib/helpers/fzf/src/algo/algo_test.go +197 -0
  35. data/lib/helpers/fzf/src/algo/normalize.go +492 -0
  36. data/lib/helpers/fzf/src/ansi.go +409 -0
  37. data/lib/helpers/fzf/src/ansi_test.go +427 -0
  38. data/lib/helpers/fzf/src/cache.go +81 -0
  39. data/lib/helpers/fzf/src/cache_test.go +39 -0
  40. data/lib/helpers/fzf/src/chunklist.go +89 -0
  41. data/lib/helpers/fzf/src/chunklist_test.go +80 -0
  42. data/lib/helpers/fzf/src/constants.go +85 -0
  43. data/lib/helpers/fzf/src/core.go +351 -0
  44. data/lib/helpers/fzf/src/history.go +96 -0
  45. data/lib/helpers/fzf/src/history_test.go +68 -0
  46. data/lib/helpers/fzf/src/item.go +44 -0
  47. data/lib/helpers/fzf/src/item_test.go +23 -0
  48. data/lib/helpers/fzf/src/matcher.go +235 -0
  49. data/lib/helpers/fzf/src/merger.go +120 -0
  50. data/lib/helpers/fzf/src/merger_test.go +88 -0
  51. data/lib/helpers/fzf/src/options.go +1691 -0
  52. data/lib/helpers/fzf/src/options_test.go +457 -0
  53. data/lib/helpers/fzf/src/pattern.go +425 -0
  54. data/lib/helpers/fzf/src/pattern_test.go +209 -0
  55. data/lib/helpers/fzf/src/protector/protector.go +8 -0
  56. data/lib/helpers/fzf/src/protector/protector_openbsd.go +10 -0
  57. data/lib/helpers/fzf/src/reader.go +201 -0
  58. data/lib/helpers/fzf/src/reader_test.go +63 -0
  59. data/lib/helpers/fzf/src/result.go +243 -0
  60. data/lib/helpers/fzf/src/result_others.go +16 -0
  61. data/lib/helpers/fzf/src/result_test.go +159 -0
  62. data/lib/helpers/fzf/src/result_x86.go +16 -0
  63. data/lib/helpers/fzf/src/terminal.go +2832 -0
  64. data/lib/helpers/fzf/src/terminal_test.go +638 -0
  65. data/lib/helpers/fzf/src/terminal_unix.go +26 -0
  66. data/lib/helpers/fzf/src/terminal_windows.go +45 -0
  67. data/lib/helpers/fzf/src/tokenizer.go +253 -0
  68. data/lib/helpers/fzf/src/tokenizer_test.go +112 -0
  69. data/lib/helpers/fzf/src/tui/dummy.go +46 -0
  70. data/lib/helpers/fzf/src/tui/light.go +987 -0
  71. data/lib/helpers/fzf/src/tui/light_unix.go +110 -0
  72. data/lib/helpers/fzf/src/tui/light_windows.go +145 -0
  73. data/lib/helpers/fzf/src/tui/tcell.go +721 -0
  74. data/lib/helpers/fzf/src/tui/tcell_test.go +392 -0
  75. data/lib/helpers/fzf/src/tui/ttyname_unix.go +47 -0
  76. data/lib/helpers/fzf/src/tui/ttyname_windows.go +14 -0
  77. data/lib/helpers/fzf/src/tui/tui.go +625 -0
  78. data/lib/helpers/fzf/src/tui/tui_test.go +20 -0
  79. data/lib/helpers/fzf/src/util/atomicbool.go +34 -0
  80. data/lib/helpers/fzf/src/util/atomicbool_test.go +17 -0
  81. data/lib/helpers/fzf/src/util/chars.go +198 -0
  82. data/lib/helpers/fzf/src/util/chars_test.go +46 -0
  83. data/lib/helpers/fzf/src/util/eventbox.go +96 -0
  84. data/lib/helpers/fzf/src/util/eventbox_test.go +61 -0
  85. data/lib/helpers/fzf/src/util/slab.go +12 -0
  86. data/lib/helpers/fzf/src/util/util.go +138 -0
  87. data/lib/helpers/fzf/src/util/util_test.go +40 -0
  88. data/lib/helpers/fzf/src/util/util_unix.go +47 -0
  89. data/lib/helpers/fzf/src/util/util_windows.go +83 -0
  90. data/lib/helpers/fzf/test/fzf.vader +175 -0
  91. data/lib/helpers/fzf/test/test_go.rb +2626 -0
  92. data/lib/helpers/fzf/uninstall +117 -0
  93. 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
+ }