From 8d6963a6a0f083350549d259606c388ae07b266f Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sat, 8 Nov 2025 11:38:56 +0100 Subject: [PATCH] fix(ui): cmdline_show is not fired after clearing the screen (#36451) Problem: Resize events during startup may clear an active external cmdline, which is then not redrawn. UI2 VimResized autocommand does not work. UI2 message appearance may be altered by inherited window options. The message separator uses the wrong fillchar. Solution: Unset cmdline_was_last_redrawn when clearing the screen, such that cmdline_show is re-emitted. Ensure set_pos function is called without arguments. Ensure such options are unset. Use 'fillchars'->msgsep. --- runtime/lua/vim/_extui.lua | 4 ++- runtime/lua/vim/_extui/messages.lua | 2 +- runtime/lua/vim/_extui/shared.lua | 4 +++ src/nvim/drawscreen.c | 1 + test/functional/ui/cmdline2_spec.lua | 36 +++++++++++++++++++++++++++ test/functional/ui/messages2_spec.lua | 30 +++++++++++----------- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/runtime/lua/vim/_extui.lua b/runtime/lua/vim/_extui.lua index 536b4b186d..bbb534723f 100644 --- a/runtime/lua/vim/_extui.lua +++ b/runtime/lua/vim/_extui.lua @@ -126,7 +126,9 @@ function M.enable(opts) api.nvim_create_autocmd({ 'VimResized', 'TabEnter' }, { group = ext.augroup, - callback = ext.msg.set_pos, + callback = function() + ext.msg.set_pos() + end, desc = 'Set cmdline and message window dimensions after shell resize or tabpage change.', }) diff --git a/runtime/lua/vim/_extui/messages.lua b/runtime/lua/vim/_extui/messages.lua index 3bd18b07ed..08b230737c 100644 --- a/runtime/lua/vim/_extui/messages.lua +++ b/runtime/lua/vim/_extui/messages.lua @@ -470,7 +470,7 @@ function M.set_pos(type) local function win_set_pos(win) local texth = type and api.nvim_win_text_height(win, {}) or {} local height = type and math.min(texth.all, math.ceil(o.lines * 0.5)) - local top = { vim.opt.fcs:get().horiz or o.ambw == 'single' and '─' or '-', 'MsgSeparator' } + local top = { vim.opt.fcs:get().msgsep or ' ', 'MsgSeparator' } local border = win ~= ext.wins.msg and { '', top, '', '', '', '', '', '' } or nil local config = { hide = false, diff --git a/runtime/lua/vim/_extui/shared.lua b/runtime/lua/vim/_extui/shared.lua index ed0932de69..912b9054a5 100644 --- a/runtime/lua/vim/_extui/shared.lua +++ b/runtime/lua/vim/_extui/shared.lua @@ -72,6 +72,10 @@ function M.check_targets() api.nvim_set_option_value('wrap', true, { scope = 'local' }) api.nvim_set_option_value('linebreak', false, { scope = 'local' }) api.nvim_set_option_value('smoothscroll', true, { scope = 'local' }) + api.nvim_set_option_value('breakindent', false, { scope = 'local' }) + api.nvim_set_option_value('foldenable', false, { scope = 'local' }) + api.nvim_set_option_value('showbreak', '', { scope = 'local' }) + api.nvim_set_option_value('spell', false, { scope = 'local' }) api.nvim_set_option_value('swapfile', false, { scope = 'local' }) api.nvim_set_option_value('modifiable', true, { scope = 'local' }) api.nvim_set_option_value('bufhidden', 'hide', { scope = 'local' }) diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index c71729871c..013983d619 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -239,6 +239,7 @@ void screenclear(void) mode_displayed = false; redraw_all_later(UPD_NOT_VALID); + cmdline_was_last_drawn = false; redraw_cmdline = true; redraw_tabline = true; redraw_popupmenu = true; diff --git a/test/functional/ui/cmdline2_spec.lua b/test/functional/ui/cmdline2_spec.lua index 0a48a10a40..928c5bfda0 100644 --- a/test/functional/ui/cmdline2_spec.lua +++ b/test/functional/ui/cmdline2_spec.lua @@ -125,3 +125,39 @@ describe('cmdline2', function() t.eq(n.eval('v:errmsg'), "E1514: 'findfunc' did not return a List type") end) end) + +describe('cmdline2', function() + it('resizing during startup shows confirm prompt #36439', function() + clear({ + args = { + '--clean', + '+lua require("vim._extui").enable({})', + "+call feedkeys(':')", + }, + }) + local screen = Screen.new() + feed('call confirm("Ok?")') + screen:try_resize(screen._width + 1, screen._height) + screen:expect([[ + | + {1:~ }|*8 + {3: }| + | + {6:Ok?} | + | + {6:[O]k: }^ | + ]]) + -- And resizing the next event loop iteration also works. + feed('k') + screen:try_resize(screen._width, screen._height + 1) + screen:expect([[ + | + {1:~ }|*9 + {3: }| + | + {6:Ok?} | + | + {6:[O]k: }^ | + ]]) + end) +end) diff --git a/test/functional/ui/messages2_spec.lua b/test/functional/ui/messages2_spec.lua index 718f661b8d..2d0923f344 100644 --- a/test/functional/ui/messages2_spec.lua +++ b/test/functional/ui/messages2_spec.lua @@ -35,7 +35,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*10 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar | ]]) @@ -44,7 +44,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*9 - {3:─────────────────────────────────────────────────────}| + {3: }| fo^o | bar | 1,3 All| @@ -54,7 +54,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*5 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar | baz | @@ -83,7 +83,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*8 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar | | @@ -115,7 +115,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*10 - {3:─────────────────────────────────────────────────────}| + {3: }| fo^o | foo | ]]) @@ -195,7 +195,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*4 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar |*5 bar [+8] | @@ -235,7 +235,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*10 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar | ]]) @@ -252,7 +252,7 @@ describe('messages2', function() screen:expect([[ ^ | {1:~ }|*10 - {3:─────────────────────────────────────────────────────}| + {3: }| foo | bar | ]]) @@ -271,7 +271,7 @@ describe('messages2', function() local top = [[ | {1:~ }|*4 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 0 | 1 | 2 | @@ -287,7 +287,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*4 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 1 [+1] | 2 | 3 | @@ -303,7 +303,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*4 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 3 [+3] | 4 | 5 | @@ -319,7 +319,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*4 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 5 [+5] | 6 | 7 | @@ -335,7 +335,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*4 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 93 [+93] | 94 | 95 | @@ -350,7 +350,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*3 - {3:───────────────────────────────────────────────────────────────────────}| + {3: }| 93 [+93] | 94 | 95 | @@ -431,7 +431,7 @@ describe('messages2', function() screen:expect([[ | {1:~ }|*9 - {3:─────────────────────────────────────────────────────}| + {3: }| ^foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo| {1: }| |