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,392 @@
1
+ // +build tcell windows
2
+
3
+ package tui
4
+
5
+ import (
6
+ "testing"
7
+
8
+ "github.com/gdamore/tcell"
9
+ "github.com/junegunn/fzf/src/util"
10
+ )
11
+
12
+ func assert(t *testing.T, context string, got interface{}, want interface{}) bool {
13
+ if got == want {
14
+ return true
15
+ } else {
16
+ t.Errorf("%s = (%T)%v, want (%T)%v", context, got, got, want, want)
17
+ return false
18
+ }
19
+ }
20
+
21
+ // Test the handling of the tcell keyboard events.
22
+ func TestGetCharEventKey(t *testing.T) {
23
+ if util.ToTty() {
24
+ // This test is skipped when output goes to terminal, because it causes
25
+ // some glitches:
26
+ // - output lines may not start at the beginning of a row which makes
27
+ // the output unreadable
28
+ // - terminal may get cleared which prevents you from seeing results of
29
+ // previous tests
30
+ // Good ways to prevent the glitches are piping the output to a pager
31
+ // or redirecting to a file. I've found `less +G` to be trouble-free.
32
+ t.Skip("Skipped because this test misbehaves in terminal, pipe to a pager or redirect output to a file to run it safely.")
33
+ } else if testing.Verbose() {
34
+ // I have observed a behaviour when this test outputted more than 8192
35
+ // bytes (32*256) into the 'less' pager, both the go's test executable
36
+ // and the pager hanged. The go's executable was blocking on printing.
37
+ // I was able to create minimal working example of that behaviour, but
38
+ // that example hanged after 12256 bytes (32*(256+127)).
39
+ t.Log("If you are piping this test to a pager and it hangs, make the pager greedy for input, e.g. 'less +G'.")
40
+ }
41
+
42
+ if !HasFullscreenRenderer() {
43
+ t.Skip("Can't test FullscreenRenderer.")
44
+ }
45
+
46
+ // construct test cases
47
+ type giveKey struct {
48
+ Type tcell.Key
49
+ Char rune
50
+ Mods tcell.ModMask
51
+ }
52
+ type wantKey = Event
53
+ type testCase struct {
54
+ giveKey
55
+ wantKey
56
+ }
57
+ /*
58
+ Some test cases are marked "fabricated". It means that giveKey value
59
+ is valid, but it is not what you get when you press the keys. For
60
+ example Ctrl+C will NOT give you tcell.KeyCtrlC, but tcell.KeyETX
61
+ (End-Of-Text character, causing SIGINT).
62
+ I was trying to accompany the fabricated test cases with real ones.
63
+
64
+ Some test cases are marked "unhandled". It means that giveKey.Type
65
+ is not present in tcell.go source code. It can still be handled via
66
+ implicit or explicit alias.
67
+
68
+ If not said otherwise, test cases are for US keyboard.
69
+
70
+ (tabstop=44)
71
+ */
72
+ tests := []testCase{
73
+
74
+ // section 1: Ctrl+(Alt)+[a-z]
75
+ {giveKey{tcell.KeyCtrlA, rune(tcell.KeyCtrlA), tcell.ModCtrl}, wantKey{CtrlA, 0, nil}},
76
+ {giveKey{tcell.KeyCtrlC, rune(tcell.KeyCtrlC), tcell.ModCtrl}, wantKey{CtrlC, 0, nil}}, // fabricated
77
+ {giveKey{tcell.KeyETX, rune(tcell.KeyETX), tcell.ModCtrl}, wantKey{CtrlC, 0, nil}}, // this is SIGINT (Ctrl+C)
78
+ {giveKey{tcell.KeyCtrlZ, rune(tcell.KeyCtrlZ), tcell.ModCtrl}, wantKey{CtrlZ, 0, nil}}, // fabricated
79
+ // KeyTab is alias for KeyTAB
80
+ {giveKey{tcell.KeyCtrlI, rune(tcell.KeyCtrlI), tcell.ModCtrl}, wantKey{Tab, 0, nil}}, // fabricated
81
+ {giveKey{tcell.KeyTab, rune(tcell.KeyTab), tcell.ModNone}, wantKey{Tab, 0, nil}}, // unhandled, actual "Tab" keystroke
82
+ {giveKey{tcell.KeyTAB, rune(tcell.KeyTAB), tcell.ModNone}, wantKey{Tab, 0, nil}}, // fabricated, unhandled
83
+ // KeyEnter is alias for KeyCR
84
+ {giveKey{tcell.KeyCtrlM, rune(tcell.KeyCtrlM), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // actual "Enter" keystroke
85
+ {giveKey{tcell.KeyCR, rune(tcell.KeyCR), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // fabricated, unhandled
86
+ {giveKey{tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // fabricated, unhandled
87
+ // Ctrl+Alt keys
88
+ {giveKey{tcell.KeyCtrlA, rune(tcell.KeyCtrlA), tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAlt, 'a', nil}}, // fabricated
89
+ {giveKey{tcell.KeyCtrlA, rune(tcell.KeyCtrlA), tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAlt, 'a', nil}}, // fabricated
90
+
91
+ // section 2: Ctrl+[ \]_]
92
+ {giveKey{tcell.KeyCtrlSpace, rune(tcell.KeyCtrlSpace), tcell.ModCtrl}, wantKey{CtrlSpace, 0, nil}}, // fabricated
93
+ {giveKey{tcell.KeyNUL, rune(tcell.KeyNUL), tcell.ModNone}, wantKey{CtrlSpace, 0, nil}}, // fabricated, unhandled
94
+ {giveKey{tcell.KeyRune, ' ', tcell.ModCtrl}, wantKey{CtrlSpace, 0, nil}}, // actual Ctrl+' '
95
+ {giveKey{tcell.KeyCtrlBackslash, rune(tcell.KeyCtrlBackslash), tcell.ModCtrl}, wantKey{CtrlBackSlash, 0, nil}},
96
+ {giveKey{tcell.KeyCtrlRightSq, rune(tcell.KeyCtrlRightSq), tcell.ModCtrl}, wantKey{CtrlRightBracket, 0, nil}},
97
+ {giveKey{tcell.KeyCtrlCarat, rune(tcell.KeyCtrlCarat), tcell.ModShift | tcell.ModCtrl}, wantKey{CtrlCaret, 0, nil}}, // fabricated
98
+ {giveKey{tcell.KeyRS, rune(tcell.KeyRS), tcell.ModShift | tcell.ModCtrl}, wantKey{CtrlCaret, 0, nil}}, // actual Ctrl+Shift+6 (i.e. Ctrl+^) keystroke
99
+ {giveKey{tcell.KeyCtrlUnderscore, rune(tcell.KeyCtrlUnderscore), tcell.ModShift | tcell.ModCtrl}, wantKey{CtrlSlash, 0, nil}},
100
+
101
+ // section 3: (Alt)+Backspace2
102
+ // KeyBackspace2 is alias for KeyDEL = 0x7F (ASCII) (allegedly unused by Windows)
103
+ // KeyDelete = 0x2E (VK_DELETE constant in Windows)
104
+ // KeyBackspace is alias for KeyBS = 0x08 (ASCII) (implicit alias with KeyCtrlH)
105
+ {giveKey{tcell.KeyBackspace2, 0, tcell.ModNone}, wantKey{BSpace, 0, nil}}, // fabricated
106
+ {giveKey{tcell.KeyBackspace2, 0, tcell.ModAlt}, wantKey{AltBS, 0, nil}}, // fabricated
107
+ {giveKey{tcell.KeyDEL, 0, tcell.ModNone}, wantKey{BSpace, 0, nil}}, // fabricated, unhandled
108
+ {giveKey{tcell.KeyDelete, 0, tcell.ModNone}, wantKey{Del, 0, nil}},
109
+ {giveKey{tcell.KeyDelete, 0, tcell.ModAlt}, wantKey{Del, 0, nil}},
110
+ {giveKey{tcell.KeyBackspace, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
111
+ {giveKey{tcell.KeyBS, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
112
+ {giveKey{tcell.KeyCtrlH, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
113
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModNone}, wantKey{BSpace, 0, nil}}, // actual "Backspace" keystroke
114
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModAlt}, wantKey{AltBS, 0, nil}}, // actual "Alt+Backspace" keystroke
115
+ {giveKey{tcell.KeyDEL, rune(tcell.KeyDEL), tcell.ModCtrl}, wantKey{BSpace, 0, nil}}, // actual "Ctrl+Backspace" keystroke
116
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift}, wantKey{BSpace, 0, nil}}, // actual "Shift+Backspace" keystroke
117
+ {giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{BSpace, 0, nil}}, // actual "Ctrl+Alt+Backspace" keystroke
118
+ {giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{BSpace, 0, nil}}, // actual "Ctrl+Shift+Backspace" keystroke
119
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift | tcell.ModAlt}, wantKey{AltBS, 0, nil}}, // actual "Shift+Alt+Backspace" keystroke
120
+ {giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{BSpace, 0, nil}}, // actual "Ctrl+Shift+Alt+Backspace" keystroke
121
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+H" keystroke
122
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAlt, 'h', nil}}, // fabricated "Ctrl+Alt+H" keystroke
123
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+Shift+H" keystroke
124
+ {giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAlt, 'h', nil}}, // fabricated "Ctrl+Shift+Alt+H" keystroke
125
+
126
+ // section 4: (Alt+Shift)+Key(Up|Down|Left|Right)
127
+ {giveKey{tcell.KeyUp, 0, tcell.ModNone}, wantKey{Up, 0, nil}},
128
+ {giveKey{tcell.KeyDown, 0, tcell.ModAlt}, wantKey{AltDown, 0, nil}},
129
+ {giveKey{tcell.KeyLeft, 0, tcell.ModShift}, wantKey{SLeft, 0, nil}},
130
+ {giveKey{tcell.KeyRight, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltSRight, 0, nil}},
131
+ {giveKey{tcell.KeyUpLeft, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
132
+ {giveKey{tcell.KeyUpRight, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
133
+ {giveKey{tcell.KeyDownLeft, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
134
+ {giveKey{tcell.KeyDownRight, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
135
+ {giveKey{tcell.KeyCenter, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
136
+ // section 5: (Insert|Home|Delete|End|PgUp|PgDn|BackTab|F1-F12)
137
+ {giveKey{tcell.KeyInsert, 0, tcell.ModNone}, wantKey{Insert, 0, nil}},
138
+ {giveKey{tcell.KeyF1, 0, tcell.ModNone}, wantKey{F1, 0, nil}},
139
+ // section 6: (Ctrl+Alt)+'rune'
140
+ {giveKey{tcell.KeyRune, 'a', tcell.ModNone}, wantKey{Rune, 'a', nil}},
141
+ {giveKey{tcell.KeyRune, 'a', tcell.ModCtrl}, wantKey{Rune, 'a', nil}}, // fabricated
142
+ {giveKey{tcell.KeyRune, 'a', tcell.ModAlt}, wantKey{Alt, 'a', nil}},
143
+ {giveKey{tcell.KeyRune, 'A', tcell.ModAlt}, wantKey{Alt, 'A', nil}},
144
+ {giveKey{tcell.KeyRune, '`', tcell.ModAlt}, wantKey{Alt, '`', nil}},
145
+ /*
146
+ "Input method" in Windows Language options:
147
+ US: "US Keyboard" does not generate any characters (and thus any events) in Ctrl+Alt+[a-z] range
148
+ CS: "Czech keyboard"
149
+ DE: "German keyboard"
150
+
151
+ Note that right Alt is not just `tcell.ModAlt` on foreign language keyboards, but it is the AltGr `tcell.ModCtrl|tcell.ModAlt`.
152
+ */
153
+ {giveKey{tcell.KeyRune, '{', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '{', nil}}, // CS: Ctrl+Alt+b = "{" // Note that this does not interfere with CtrlB, since the "b" is replaced with "{" on OS level
154
+ {giveKey{tcell.KeyRune, '$', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '$', nil}}, // CS: Ctrl+Alt+ů = "$"
155
+ {giveKey{tcell.KeyRune, '~', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '~', nil}}, // CS: Ctrl+Alt++ = "~"
156
+ {giveKey{tcell.KeyRune, '`', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '`', nil}}, // CS: Ctrl+Alt+ý,Space = "`" // this is dead key, space is required to emit the char
157
+
158
+ {giveKey{tcell.KeyRune, '{', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '{', nil}}, // DE: Ctrl+Alt+7 = "{"
159
+ {giveKey{tcell.KeyRune, '@', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, '@', nil}}, // DE: Ctrl+Alt+q = "@"
160
+ {giveKey{tcell.KeyRune, 'µ', tcell.ModCtrl | tcell.ModAlt}, wantKey{Rune, 'µ', nil}}, // DE: Ctrl+Alt+m = "µ"
161
+
162
+ // section 7: Esc
163
+ // KeyEsc and KeyEscape are aliases for KeyESC
164
+ {giveKey{tcell.KeyEsc, rune(tcell.KeyEsc), tcell.ModNone}, wantKey{ESC, 0, nil}}, // fabricated
165
+ {giveKey{tcell.KeyESC, rune(tcell.KeyESC), tcell.ModNone}, wantKey{ESC, 0, nil}}, // unhandled
166
+ {giveKey{tcell.KeyEscape, rune(tcell.KeyEscape), tcell.ModNone}, wantKey{ESC, 0, nil}}, // fabricated, unhandled
167
+ {giveKey{tcell.KeyESC, rune(tcell.KeyESC), tcell.ModCtrl}, wantKey{ESC, 0, nil}}, // actual Ctrl+[ keystroke
168
+ {giveKey{tcell.KeyCtrlLeftSq, rune(tcell.KeyCtrlLeftSq), tcell.ModCtrl}, wantKey{ESC, 0, nil}}, // fabricated, unhandled
169
+
170
+ // section 8: Invalid
171
+ {giveKey{tcell.KeyRune, 'a', tcell.ModMeta}, wantKey{Rune, 'a', nil}}, // fabricated
172
+ {giveKey{tcell.KeyF24, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}},
173
+ {giveKey{tcell.KeyHelp, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
174
+ {giveKey{tcell.KeyExit, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
175
+ {giveKey{tcell.KeyClear, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // unhandled, actual keystroke Numpad_5 with Numlock OFF
176
+ {giveKey{tcell.KeyCancel, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
177
+ {giveKey{tcell.KeyPrint, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
178
+ {giveKey{tcell.KeyPause, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // unhandled
179
+
180
+ }
181
+ r := NewFullscreenRenderer(&ColorTheme{}, false, false)
182
+ r.Init()
183
+
184
+ // run and evaluate the tests
185
+ for _, test := range tests {
186
+ // generate key event
187
+ giveEvent := tcell.NewEventKey(test.giveKey.Type, test.giveKey.Char, test.giveKey.Mods)
188
+ _screen.PostEventWait(giveEvent)
189
+ t.Logf("giveEvent = %T{key: %v, ch: %q (%[3]v), mod: %#04b}\n", giveEvent, giveEvent.Key(), giveEvent.Rune(), giveEvent.Modifiers())
190
+
191
+ // process the event in fzf and evaluate the test
192
+ gotEvent := r.GetChar()
193
+ // skip Resize events, those are sometimes put in the buffer outside of this test
194
+ for gotEvent.Type == Resize {
195
+ t.Logf("Resize swallowed")
196
+ gotEvent = r.GetChar()
197
+ }
198
+ t.Logf("wantEvent = %T{Type: %v, Char: %q (%[3]v)}\n", test.wantKey, test.wantKey.Type, test.wantKey.Char)
199
+ t.Logf("gotEvent = %T{Type: %v, Char: %q (%[3]v)}\n", gotEvent, gotEvent.Type, gotEvent.Char)
200
+
201
+ assert(t, "r.GetChar().Type", gotEvent.Type, test.wantKey.Type)
202
+ assert(t, "r.GetChar().Char", gotEvent.Char, test.wantKey.Char)
203
+ }
204
+
205
+ r.Close()
206
+ }
207
+
208
+ /*
209
+ Quick reference
210
+ ---------------
211
+
212
+ (tabstop=18)
213
+ (this is not mapping table, it merely puts multiple constants ranges in one table)
214
+
215
+ ¹) the two columns are each other implicit alias
216
+ ²) explicit aliases here
217
+
218
+ %v section # tcell ctrl key¹ tcell ctrl char¹ tcell alias² tui constants tcell named keys tcell mods
219
+ -- --------- -------------- --------------- ----------- ------------- ---------------- ----------
220
+ 0 2 KeyCtrlSpace KeyNUL = ^@ Rune ModNone
221
+ 1 1 KeyCtrlA KeySOH = ^A CtrlA ModShift
222
+ 2 1 KeyCtrlB KeySTX = ^B CtrlB ModCtrl
223
+ 3 1 KeyCtrlC KeyETX = ^C CtrlC
224
+ 4 1 KeyCtrlD KeyEOT = ^D CtrlD ModAlt
225
+ 5 1 KeyCtrlE KeyENQ = ^E CtrlE
226
+ 6 1 KeyCtrlF KeyACK = ^F CtrlF
227
+ 7 1 KeyCtrlG KeyBEL = ^G CtrlG
228
+ 8 1 KeyCtrlH KeyBS = ^H KeyBackspace CtrlH ModMeta
229
+ 9 1 KeyCtrlI KeyTAB = ^I KeyTab Tab
230
+ 10 1 KeyCtrlJ KeyLF = ^J CtrlJ
231
+ 11 1 KeyCtrlK KeyVT = ^K CtrlK
232
+ 12 1 KeyCtrlL KeyFF = ^L CtrlL
233
+ 13 1 KeyCtrlM KeyCR = ^M KeyEnter CtrlM
234
+ 14 1 KeyCtrlN KeySO = ^N CtrlN
235
+ 15 1 KeyCtrlO KeySI = ^O CtrlO
236
+ 16 1 KeyCtrlP KeyDLE = ^P CtrlP
237
+ 17 1 KeyCtrlQ KeyDC1 = ^Q CtrlQ
238
+ 18 1 KeyCtrlR KeyDC2 = ^R CtrlR
239
+ 19 1 KeyCtrlS KeyDC3 = ^S CtrlS
240
+ 20 1 KeyCtrlT KeyDC4 = ^T CtrlT
241
+ 21 1 KeyCtrlU KeyNAK = ^U CtrlU
242
+ 22 1 KeyCtrlV KeySYN = ^V CtrlV
243
+ 23 1 KeyCtrlW KeyETB = ^W CtrlW
244
+ 24 1 KeyCtrlX KeyCAN = ^X CtrlX
245
+ 25 1 KeyCtrlY KeyEM = ^Y CtrlY
246
+ 26 1 KeyCtrlZ KeySUB = ^Z CtrlZ
247
+ 27 7 KeyCtrlLeftSq KeyESC = ^[ KeyEsc, KeyEscape ESC
248
+ 28 2 KeyCtrlBackslash KeyFS = ^\ CtrlSpace
249
+ 29 2 KeyCtrlRightSq KeyGS = ^] CtrlBackSlash
250
+ 30 2 KeyCtrlCarat KeyRS = ^^ CtrlRightBracket
251
+ 31 2 KeyCtrlUnderscore KeyUS = ^_ CtrlCaret
252
+ 32 CtrlSlash
253
+ 33 Invalid
254
+ 34 Resize
255
+ 35 Mouse
256
+ 36 DoubleClick
257
+ 37 LeftClick
258
+ 38 RightClick
259
+ 39 BTab
260
+ 40 BSpace
261
+ 41 Del
262
+ 42 PgUp
263
+ 43 PgDn
264
+ 44 Up
265
+ 45 Down
266
+ 46 Left
267
+ 47 Right
268
+ 48 Home
269
+ 49 End
270
+ 50 Insert
271
+ 51 SUp
272
+ 52 SDown
273
+ 53 SLeft
274
+ 54 SRight
275
+ 55 F1
276
+ 56 F2
277
+ 57 F3
278
+ 58 F4
279
+ 59 F5
280
+ 60 F6
281
+ 61 F7
282
+ 62 F8
283
+ 63 F9
284
+ 64 F10
285
+ 65 F11
286
+ 66 F12
287
+ 67 Change
288
+ 68 BackwardEOF
289
+ 69 AltBS
290
+ 70 AltUp
291
+ 71 AltDown
292
+ 72 AltLeft
293
+ 73 AltRight
294
+ 74 AltSUp
295
+ 75 AltSDown
296
+ 76 AltSLeft
297
+ 77 AltSRight
298
+ 78 Alt
299
+ 79 CtrlAlt
300
+ ..
301
+ 127 3 KeyDEL KeyBackspace2
302
+ ..
303
+ 256 6 KeyRune
304
+ 257 4 KeyUp
305
+ 258 4 KeyDown
306
+ 259 4 KeyRight
307
+ 260 4 KeyLeft
308
+ 261 8 KeyUpLeft
309
+ 262 8 KeyUpRight
310
+ 263 8 KeyDownLeft
311
+ 264 8 KeyDownRight
312
+ 265 8 KeyCenter
313
+ 266 5 KeyPgUp
314
+ 267 5 KeyPgDn
315
+ 268 5 KeyHome
316
+ 269 5 KeyEnd
317
+ 270 5 KeyInsert
318
+ 271 5 KeyDelete
319
+ 272 8 KeyHelp
320
+ 273 8 KeyExit
321
+ 274 8 KeyClear
322
+ 275 8 KeyCancel
323
+ 276 8 KeyPrint
324
+ 277 8 KeyPause
325
+ 278 5 KeyBacktab
326
+ 279 5 KeyF1
327
+ 280 5 KeyF2
328
+ 281 5 KeyF3
329
+ 282 5 KeyF4
330
+ 283 5 KeyF5
331
+ 284 5 KeyF6
332
+ 285 5 KeyF7
333
+ 286 5 KeyF8
334
+ 287 5 KeyF9
335
+ 288 5 KeyF10
336
+ 289 5 KeyF11
337
+ 290 5 KeyF12
338
+ 291 8 KeyF13
339
+ 292 8 KeyF14
340
+ 293 8 KeyF15
341
+ 294 8 KeyF16
342
+ 295 8 KeyF17
343
+ 296 8 KeyF18
344
+ 297 8 KeyF19
345
+ 298 8 KeyF20
346
+ 299 8 KeyF21
347
+ 300 8 KeyF22
348
+ 301 8 KeyF23
349
+ 302 8 KeyF24
350
+ 303 8 KeyF25
351
+ 304 8 KeyF26
352
+ 305 8 KeyF27
353
+ 306 8 KeyF28
354
+ 307 8 KeyF29
355
+ 308 8 KeyF30
356
+ 309 8 KeyF31
357
+ 310 8 KeyF32
358
+ 311 8 KeyF33
359
+ 312 8 KeyF34
360
+ 313 8 KeyF35
361
+ 314 8 KeyF36
362
+ 315 8 KeyF37
363
+ 316 8 KeyF38
364
+ 317 8 KeyF39
365
+ 318 8 KeyF40
366
+ 319 8 KeyF41
367
+ 320 8 KeyF42
368
+ 321 8 KeyF43
369
+ 322 8 KeyF44
370
+ 323 8 KeyF45
371
+ 324 8 KeyF46
372
+ 325 8 KeyF47
373
+ 326 8 KeyF48
374
+ 327 8 KeyF49
375
+ 328 8 KeyF50
376
+ 329 8 KeyF51
377
+ 330 8 KeyF52
378
+ 331 8 KeyF53
379
+ 332 8 KeyF54
380
+ 333 8 KeyF55
381
+ 334 8 KeyF56
382
+ 335 8 KeyF57
383
+ 336 8 KeyF58
384
+ 337 8 KeyF59
385
+ 338 8 KeyF60
386
+ 339 8 KeyF61
387
+ 340 8 KeyF62
388
+ 341 8 KeyF63
389
+ 342 8 KeyF64
390
+ -- --------- -------------- --------------- ----------- ------------- ---------------- ----------
391
+ %v section # tcell ctrl key tcell ctrl char tcell alias tui constants tcell named keys tcell mods
392
+ */
@@ -0,0 +1,47 @@
1
+ // +build !windows
2
+
3
+ package tui
4
+
5
+ import (
6
+ "io/ioutil"
7
+ "os"
8
+ "syscall"
9
+ )
10
+
11
+ var devPrefixes = [...]string{"/dev/pts/", "/dev/"}
12
+
13
+ func ttyname() string {
14
+ var stderr syscall.Stat_t
15
+ if syscall.Fstat(2, &stderr) != nil {
16
+ return ""
17
+ }
18
+
19
+ for _, prefix := range devPrefixes {
20
+ files, err := ioutil.ReadDir(prefix)
21
+ if err != nil {
22
+ continue
23
+ }
24
+
25
+ for _, file := range files {
26
+ if stat, ok := file.Sys().(*syscall.Stat_t); ok && stat.Rdev == stderr.Rdev {
27
+ return prefix + file.Name()
28
+ }
29
+ }
30
+ }
31
+ return ""
32
+ }
33
+
34
+ // TtyIn returns terminal device to be used as STDIN, falls back to os.Stdin
35
+ func TtyIn() *os.File {
36
+ in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
37
+ if err != nil {
38
+ tty := ttyname()
39
+ if len(tty) > 0 {
40
+ if in, err := os.OpenFile(tty, syscall.O_RDONLY, 0); err == nil {
41
+ return in
42
+ }
43
+ }
44
+ return os.Stdin
45
+ }
46
+ return in
47
+ }
@@ -0,0 +1,14 @@
1
+ // +build windows
2
+
3
+ package tui
4
+
5
+ import "os"
6
+
7
+ func ttyname() string {
8
+ return ""
9
+ }
10
+
11
+ // TtyIn on Windows returns os.Stdin
12
+ func TtyIn() *os.File {
13
+ return os.Stdin
14
+ }