mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
events: allow event processing in getchar()
this is consistent with vim, and is necessary for plugins that implement their own input modes using "getchar()" and still want to do async event processing.
This commit is contained in:
parent
5a61ff188c
commit
719dae2e01
@ -9527,24 +9527,35 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
varnumber_T n;
|
varnumber_T n;
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
|
|
||||||
/* Position the cursor. Needed after a message that ends in a space. */
|
|
||||||
ui_cursor_goto(msg_row, msg_col);
|
|
||||||
|
|
||||||
++no_mapping;
|
++no_mapping;
|
||||||
++allow_keys;
|
++allow_keys;
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
if (argvars[0].v_type == VAR_UNKNOWN)
|
// Position the cursor. Needed after a message that ends in a space,
|
||||||
/* getchar(): blocking wait. */
|
// or if event processing caused a redraw.
|
||||||
|
ui_cursor_goto(msg_row, msg_col);
|
||||||
|
|
||||||
|
if (argvars[0].v_type == VAR_UNKNOWN) {
|
||||||
|
// getchar(): blocking wait.
|
||||||
|
if (!(char_avail() || using_script() || input_available())) {
|
||||||
|
input_enable_events();
|
||||||
|
(void)os_inchar(NULL, 0, -1, 0);
|
||||||
|
input_disable_events();
|
||||||
|
if (!multiqueue_empty(main_loop.events)) {
|
||||||
|
multiqueue_process_events(main_loop.events);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
n = safe_vgetc();
|
n = safe_vgetc();
|
||||||
else if (get_tv_number_chk(&argvars[0], &error) == 1)
|
} else if (get_tv_number_chk(&argvars[0], &error) == 1) {
|
||||||
/* getchar(1): only check if char avail */
|
// getchar(1): only check if char avail
|
||||||
n = vpeekc_any();
|
n = vpeekc_any();
|
||||||
else if (error || vpeekc_any() == NUL)
|
} else if (error || vpeekc_any() == NUL) {
|
||||||
/* illegal argument or getchar(0) and no char avail: return zero */
|
// illegal argument or getchar(0) and no char avail: return zero
|
||||||
n = 0;
|
n = 0;
|
||||||
else
|
} else {
|
||||||
/* getchar(0) and char avail: return char */
|
// getchar(0) and char avail: return char
|
||||||
n = safe_vgetc();
|
n = safe_vgetc();
|
||||||
|
}
|
||||||
|
|
||||||
if (n == K_IGNORE)
|
if (n == K_IGNORE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
|
|||||||
local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval
|
local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval
|
||||||
local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
|
local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
|
||||||
local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs
|
local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs
|
||||||
|
local curbufmeths = helpers.curbufmeths
|
||||||
|
|
||||||
describe('timers', function()
|
describe('timers', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
@ -62,19 +63,76 @@ describe('timers', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('are paused when event processing is disabled', function()
|
it('are paused when event processing is disabled', function()
|
||||||
-- this is not the intended behavior, but at least there will
|
execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
|
||||||
-- not be a burst of queued up callbacks
|
|
||||||
execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
|
|
||||||
run(nil, nil, nil, 100)
|
run(nil, nil, nil, 100)
|
||||||
local count = eval("g:val")
|
local count = eval("g:val")
|
||||||
|
-- shows two line error message and thus invokes the return prompt.
|
||||||
|
-- if we start to allow event processing here, we need to change this test.
|
||||||
|
execute("throw 'fatal error'")
|
||||||
|
run(nil, nil, nil, 300)
|
||||||
|
feed("<cr>")
|
||||||
|
local diff = eval("g:val") - count
|
||||||
|
ok(0 <= diff and diff <= 4)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('are triggered in blocking getchar() call', function()
|
||||||
|
execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
|
||||||
nvim_async("command", "let g:c = getchar()")
|
nvim_async("command", "let g:c = getchar()")
|
||||||
run(nil, nil, nil, 300)
|
run(nil, nil, nil, 300)
|
||||||
feed("c")
|
feed("c")
|
||||||
local diff = eval("g:val") - count
|
local count = eval("g:val")
|
||||||
ok(0 <= diff and diff <= 2)
|
ok(count >= 5)
|
||||||
eq(99, eval("g:c"))
|
eq(99, eval("g:c"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can invoke redraw in blocking getchar() call', function()
|
||||||
|
local screen = Screen.new(40, 6)
|
||||||
|
screen:attach()
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {bold=true, foreground=Screen.colors.Blue},
|
||||||
|
})
|
||||||
|
|
||||||
|
curbufmeths.set_lines(0, -1, true, {"ITEM 1", "ITEM 2"})
|
||||||
|
source([[
|
||||||
|
func! AddItem(timer)
|
||||||
|
call nvim_buf_set_lines(0, 2, 2, v:true, ['ITEM 3'])
|
||||||
|
redraw
|
||||||
|
endfunc
|
||||||
|
call timer_start(200, 'AddItem')
|
||||||
|
]])
|
||||||
|
nvim_async("command", "let g:c2 = getchar()")
|
||||||
|
|
||||||
|
screen:expect([[
|
||||||
|
ITEM 1 |
|
||||||
|
ITEM 2 |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
^ |
|
||||||
|
]])
|
||||||
|
|
||||||
|
screen:sleep(200)
|
||||||
|
screen:expect([[
|
||||||
|
ITEM 1 |
|
||||||
|
ITEM 2 |
|
||||||
|
ITEM 3 |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
^ |
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed("3")
|
||||||
|
eq(51, eval("g:c2"))
|
||||||
|
screen:expect([[
|
||||||
|
^ITEM 1 |
|
||||||
|
ITEM 2 |
|
||||||
|
ITEM 3 |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
it('can be stopped', function()
|
it('can be stopped', function()
|
||||||
local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})")
|
local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})")
|
||||||
eq(0,eval("g:val"))
|
eq(0,eval("g:val"))
|
||||||
|
Loading…
Reference in New Issue
Block a user