doing 2.0.18 → 2.0.22

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