aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-11-10 15:24:36 +0800
committerGitHub <noreply@github.com>2023-11-10 15:24:36 +0800
commitd5a85d737aa2a5c3a64ef0aa5b01672b7ed49c09 (patch)
treed3ade990979b1c8f0ad3890fc8a6eb5b90848f68
parentbf5cf8ae82f2a164fba6ae063e0f5b7cb7c1df7b (diff)
downloadrneovim-d5a85d737aa2a5c3a64ef0aa5b01672b7ed49c09.tar.gz
rneovim-d5a85d737aa2a5c3a64ef0aa5b01672b7ed49c09.tar.bz2
rneovim-d5a85d737aa2a5c3a64ef0aa5b01672b7ed49c09.zip
fix(f_wait): flush UI before blocking (#25962)
-rw-r--r--src/nvim/eval/funcs.c3
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/lua/executor.c2
-rw-r--r--src/nvim/state.c2
-rw-r--r--test/functional/core/job_spec.lua38
-rw-r--r--test/functional/lua/vim_spec.lua2
-rw-r--r--test/functional/ui/messages_spec.lua59
7 files changed, 82 insertions, 26 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 36d368a913..2d8ad458f1 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2911,6 +2911,9 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool error = false;
const int called_emsg_before = called_emsg;
+ // Flush screen updates before blocking.
+ ui_flush();
+
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, timeout,
eval_expr_typval(&expr, false, &argv, 0, &exprval) != OK
|| tv_get_number_chk(&exprval, &error)
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 8b1e2f9105..2370df916c 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1723,7 +1723,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
// getchar(): blocking wait.
// TODO(bfredl): deduplicate shared logic with state_enter ?
if (!char_avail()) {
- // flush output before waiting
+ // Flush screen updates before blocking.
ui_flush();
(void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
if (!multiqueue_empty(main_loop.events)) {
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 3333c73bfd..876a5c34bd 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -463,7 +463,7 @@ static int nlua_wait(lua_State *lstate)
int pcall_status = 0;
bool callback_result = false;
- // Flush UI before blocking
+ // Flush screen updates before blocking.
ui_flush();
LOOP_PROCESS_EVENTS_UNTIL(&main_loop,
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 61e8d8d2ff..d2466e4248 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -70,7 +70,7 @@ getkey:
update_screen();
setcursor(); // put cursor back where it belongs
}
- // Flush screen updates before blocking
+ // Flush screen updates before blocking.
ui_flush();
// Call `os_inchar` directly to block for events or user input without
// consuming anything from `input_buffer`(os/input.c) or calling the
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index befbd4bc3b..038368c387 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -875,25 +875,41 @@ describe('jobs', function()
end)
end)
- it('hides cursor when waiting', function()
- local screen = Screen.new(30, 3)
+ it('hides cursor and flushes messages before blocking', function()
+ local screen = Screen.new(50, 6)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue1, bold = true};
+ [0] = {foreground = Screen.colors.Blue, bold = true}; -- NonText
+ [1] = {bold = true, reverse = true}; -- MsgSeparator
+ [2] = {bold = true, foreground = Screen.colors.SeaGreen}; -- MoreMsg
})
screen:attach()
command([[let g:id = jobstart([v:progpath, '--clean', '--headless'])]])
- feed_command('call jobwait([g:id], 300)')
+ source([[
+ func PrintAndWait()
+ echon "aaa\nbbb"
+ call jobwait([g:id], 300)
+ echon "\nccc"
+ endfunc
+ ]])
+ feed_command('call PrintAndWait()')
screen:expect{grid=[[
- |
- {0:~ }|
- :call jobwait([g:id], 300) |
+ |
+ {0:~ }|
+ {0:~ }|
+ {1: }|
+ aaa |
+ bbb |
]], timeout=100}
- funcs.jobstop(meths.get_var('id'))
screen:expect{grid=[[
- ^ |
- {0:~ }|
- :call jobwait([g:id], 300) |
+ |
+ {1: }|
+ aaa |
+ bbb |
+ ccc |
+ {2:Press ENTER or type command to continue}^ |
]]}
+ feed('<CR>')
+ funcs.jobstop(meths.get_var('id'))
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 1ebfa9dd1d..a8a72f20c9 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2559,7 +2559,6 @@ describe('lua stdlib', function()
]])
end)
-
it('should not block other events', function()
eq({time = true, wait_result = true}, exec_lua[[
start_time = get_time()
@@ -2601,6 +2600,7 @@ describe('lua stdlib', function()
}
]])
end)
+
it('should work with vim.defer_fn', function()
eq({time = true, wait_result = true}, exec_lua[[
start_time = get_time()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index a5b2474bc5..215e763fd1 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1312,17 +1312,54 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
]])
end)
- it('echo messages are shown correctly when getchar() immediately follows', function()
- feed([[:echo 'foo' | echo 'bar' | call getchar()<CR>]])
- screen:expect([[
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {3: }|
- foo |
- bar^ |
- ]])
+ describe('echo messages are shown when immediately followed by', function()
+ --- @param to_block string command to cause a blocking wait
+ --- @param to_unblock number|string number: timeout for blocking screen
+ --- string: keys to stop the blocking wait
+ local function test_flush_before_block(to_block, to_unblock)
+ local timeout = type(to_unblock) == 'number' and to_unblock or nil
+ exec(([[
+ func PrintAndWait()
+ echon "aaa\nbbb"
+ %s
+ echon "\nccc"
+ endfunc
+ ]]):format(to_block))
+ feed(':call PrintAndWait()<CR>')
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3: }|
+ aaa |
+ bbb^ |
+ ]], timeout=timeout}
+ if type(to_unblock) == 'string' then
+ feed(to_unblock)
+ end
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {3: }|
+ aaa |
+ bbb |
+ ccc |
+ {4:Press ENTER or type command to continue}^ |
+ ]]}
+ end
+
+ it('getchar()', function()
+ test_flush_before_block([[call getchar()]], 'k')
+ end)
+
+ it('wait()', function()
+ test_flush_before_block([[call wait(300, '0')]], 100)
+ end)
+
+ it('lua vim.wait()', function()
+ test_flush_before_block([[lua vim.wait(300, function() end)]], 100)
+ end)
end)
it('consecutive calls to win_move_statusline() work after multiline message #21014',function()