From e7ae1b3c10ad16713b0f0353eb2bb445b0e73c89 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 26 Aug 2026 08:32:58 -0400 Subject: [PATCH] fix(ui2): cmdwin is not special #41508 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Unreliable ui2 test: FAILED …/ui/messages2_spec.lua @ 277: messages2 multiline messages and pager …/ui/messages2_spec.lua:277: Row 1 did not match. Expected: ... |*{1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | |*{1::}messages | |*{1::}^ | ... Actual: ... |*{9:vim.schedule callback: ...ork/neovim/neovim/runt [+7]}| Solution: ui2 is doing contortions to handle the old cmdwin behavior; stop doing that, it's no longer necessary since b2bf7bcfb151. --- runtime/lua/vim/_core/cmdwin.lua | 6 ++++++ runtime/lua/vim/_core/ui2/messages.lua | 20 ++++++++------------ test/functional/ui/messages2_spec.lua | 12 +++++++----- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/runtime/lua/vim/_core/cmdwin.lua b/runtime/lua/vim/_core/cmdwin.lua index 16727b81a0..88b957c1ce 100644 --- a/runtime/lua/vim/_core/cmdwin.lua +++ b/runtime/lua/vim/_core/cmdwin.lua @@ -147,6 +147,12 @@ function M._cleanup() end end +--- cmdwin window, or nil if not open. +--- @return integer? +function M.win() + return state and vim.api.nvim_win_is_valid(state.win) and state.win or nil +end + --- Closes the cmdwin and returns its current line and type. --- @return string line, string type local function _close() diff --git a/runtime/lua/vim/_core/ui2/messages.lua b/runtime/lua/vim/_core/ui2/messages.lua index 6c2c3da280..bf582bd7f0 100644 --- a/runtime/lua/vim/_core/ui2/messages.lua +++ b/runtime/lua/vim/_core/ui2/messages.lua @@ -665,7 +665,6 @@ local dialog_on_key = function(_, typed) end end -local was_cmdwin = '' ---@param min integer Minimum window height. local function win_row_height_border(tgt, min) local h = (tgt ~= 'cmd' and ui.cfg.msg[tgt].height or 0) --[[@as number]] @@ -675,7 +674,8 @@ local function win_row_height_border(tgt, min) math.max(1, min), min < o.lines - ui.cmdheight end - local cmdwin = fn.getcmdwintype() ~= was_cmdwin and api.nvim_win_get_height(0) or 0 + local cmdwin_win = require('vim._core.cmdwin').win() + local cmdwin = cmdwin_win and api.nvim_win_get_height(cmdwin_win) or 0 local global_stl = (cmdwin > 0 or o.laststatus == 3) and 1 or 0 local row = 1 - cmdwin - global_stl local top = min < o.lines - ui.cmdheight - global_stl - cmdwin @@ -684,15 +684,15 @@ local function win_row_height_border(tgt, min) end local function enter_pager() - -- Cannot leave the cmdwin to enter the pager, so close and re-open it. - in_pager, was_cmdwin = true, fn.getcmdwintype() - if was_cmdwin ~= '' then - api.nvim_command('quit') - elseif M.cmd_on_key then + in_pager = true + if M.cmd_on_key then api.nvim_feedkeys(vim.keycode(''), 'tn', false) end - -- Cmdwin is closed one event iteration later so schedule in case it was open. + -- Schedule: the fed above is processed one event iteration later. vim.schedule(function() + if not api.nvim_win_is_valid(ui.wins.pager) then + return -- Pager was already closed somehow. + end local height, id = api.nvim_win_get_height(ui.wins.pager), 0 api.nvim_set_option_value('eiw', '', { scope = 'local', win = ui.wins.pager }) api.nvim_set_current_win(ui.wins.pager) @@ -716,10 +716,6 @@ local function enter_pager() else pcall(api.nvim_set_option_value, 'eiw', 'all', { scope = 'local', win = ui.wins.pager }) api.nvim_del_autocmd(id) - if was_cmdwin ~= '' then - api.nvim_feedkeys('q' .. was_cmdwin, 'n', false) - was_cmdwin = '' - end end pcall(api.nvim_win_set_config, ui.wins.pager, cfg) end) diff --git a/test/functional/ui/messages2_spec.lua b/test/functional/ui/messages2_spec.lua index 7e3ab78cc0..6df427625c 100644 --- a/test/functional/ui/messages2_spec.lua +++ b/test/functional/ui/messages2_spec.lua @@ -265,24 +265,26 @@ describe('messages2', function() | ]]) feed(':messages') + -- Cmdwin stays open behind the pager: it is a regular window (#40312). screen:expect([[ ^foo | foo |*4 - {1:~ }|*7 + {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1::} | + {1:~ }|*5 {3:[Pager] 1,1 Top}| {16::}{15:messages} | ]]) - -- Cmdwin is restored after pager is closed. + -- Closing the pager returns to the cmdwin, unchanged (it was never closed). feed('q') screen:expect([[ x | {1:~ }|*3 ─────────────────────────────────────────────────────| {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}messages | {1::}^ | - {1:~ }|*4 - {3:[Command Line] 3,0-1 All}| + {1:~ }|*5 + {3:[Command Line] 2,0-1 All}| {16::}{15:messages} | ]]) -- Configured maximum height.