doing 2.0.20 → 2.0.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/doing.rdoc +1 -1
- data/lib/doing/log_adapter.rb +3 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +19 -8
- 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 +88 -2
@@ -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
|
+
}
|