+43
-8
lines changedFilter options
+43
-8
lines changed Original file line number Diff line number Diff line change
@@ -3180,7 +3180,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
3180
3180
if (argvars[0].v_type == VAR_UNKNOWN) {
3181
3181
// getchar(): blocking wait.
3182
3182
// TODO(bfredl): deduplicate shared logic with state_enter ?
3183
-
if (!(char_avail() || using_script() || input_available())) {
3183
+
if (!char_avail()) {
3184
3184
(void)os_inchar(NULL, 0, -1, 0, main_loop.events);
3185
3185
if (!multiqueue_empty(main_loop.events)) {
3186
3186
state_handle_k_event();
Original file line number Diff line number Diff line change
@@ -39,10 +39,16 @@ void state_enter(VimState *s)
39
39
int key;
40
40
41
41
getkey:
42
-
if (char_avail() || using_script() || input_available()) {
43
-
// Don't block for events if there's a character already available for
44
-
// processing. Characters can come from mappings, scripts and other
45
-
// sources, so this scenario is very common.
42
+
// Expand mappings first by calling vpeekc() directly.
43
+
// - If vpeekc() returns non-NUL, there is a character already available for processing, so
44
+
// don't block for events. vgetc() may still block, in case of an incomplete UTF-8 sequence.
45
+
// - If vpeekc() returns NUL, vgetc() will block, and there are three cases:
46
+
// - There is no input available.
47
+
// - All of available input maps to an empty string.
48
+
// - There is an incomplete mapping.
49
+
// A blocking wait for a character should only be done in the third case, which is the only
50
+
// case of the three where typebuf.tb_len > 0 after vpeekc() returns NUL.
51
+
if (vpeekc() != NUL || typebuf.tb_len > 0) {
46
52
key = safe_vgetc();
47
53
} else if (!multiqueue_empty(main_loop.events)) {
48
54
// Event was made available after the last multiqueue_process_events call
@@ -55,9 +61,11 @@ void state_enter(VimState *s)
55
61
// mapping engine.
56
62
(void)os_inchar(NULL, 0, -1, 0, main_loop.events);
57
63
// If an event was put into the queue, we send K_EVENT directly.
58
-
key = !multiqueue_empty(main_loop.events)
59
-
? K_EVENT
60
-
: safe_vgetc();
64
+
if (!multiqueue_empty(main_loop.events)) {
65
+
key = K_EVENT;
66
+
} else {
67
+
goto getkey;
68
+
}
61
69
}
62
70
63
71
if (key == K_EVENT) {
Original file line number Diff line number Diff line change
@@ -140,6 +140,25 @@ describe('input utf sequences that contain CSI (0x9B)', function()
140
140
end)
141
141
end)
142
142
143
+
describe('input split utf sequences', function()
144
+
it('ok', function()
145
+
local str = '►'
146
+
feed('i' .. str:sub(1, 1))
147
+
helpers.sleep(10)
148
+
feed(str:sub(2, 3))
149
+
expect('►')
150
+
end)
151
+
152
+
it('can be mapped', function()
153
+
command('inoremap ► E296BA')
154
+
local str = '►'
155
+
feed('i' .. str:sub(1, 1))
156
+
helpers.sleep(10)
157
+
feed(str:sub(2, 3))
158
+
expect('E296BA')
159
+
end)
160
+
end)
161
+
143
162
describe('input non-printable chars', function()
144
163
after_each(function()
145
164
os.remove('Xtest-overwrite')
Original file line number Diff line number Diff line change
@@ -272,4 +272,12 @@ describe('timers', function()
272
272
]]
273
273
eq("Vim(call):E48: Not allowed in sandbox", exc_exec("sandbox call timer_start(0, 'Scary')"))
274
274
end)
275
+
276
+
it('can be triggered after an empty string <expr> mapping', function()
277
+
local screen = Screen.new(40, 6)
278
+
screen:attach()
279
+
command([=[imap <expr> <F2> [timer_start(0, { _ -> execute("throw 'x'", "") }), ''][-1]]=])
280
+
feed('i<F2>')
281
+
screen:expect({any='E605: Exception not caught: x'})
282
+
end)
275
283
end)
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4