fix(extui): cmdline visibility, cmdheight cursor position (#33774)

Problem:  The cmdline popupmenu is hidden behind extui windows.
          'showmode' message is drawn over the cmdline.
          Changing the 'cmdheight' to accommodate space for the text in
          the cmdline may change the current cursor position.
Solution: Ensure kZIndexMessages < zindex < kZIndexCmdlinePopupMenu.
          Clear the 'showmode' message when the cmdline level is negative.
          Temporarily set 'splitkeep' = "screen" when changing the 'cmdheight'.
This commit is contained in:
luukvbaal
2025-05-02 19:46:30 +02:00
committed by GitHub
parent c916bdf329
commit 39a5b7f239
3 changed files with 13 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ local M = {
indent = 0, -- Current indent for block event. indent = 0, -- Current indent for block event.
prompt = false, -- Whether a prompt is active; messages are placed in the 'prompt' window. prompt = false, -- Whether a prompt is active; messages are placed in the 'prompt' window.
row = 0, -- Current row in the cmdline buffer, > 0 for block events. row = 0, -- Current row in the cmdline buffer, > 0 for block events.
level = -1, -- Current cmdline level, < 0 when inactive (otherwise unused).
} }
--- Set the 'cmdheight' and cmdline window height. Reposition message windows. --- Set the 'cmdheight' and cmdline window height. Reposition message windows.
@@ -20,7 +21,11 @@ local function win_config(win, hide, height)
api.nvim_win_set_height(win, height) api.nvim_win_set_height(win, height)
end end
if vim.o.cmdheight ~= height then if vim.o.cmdheight ~= height then
vim.cmd('noautocmd set cmdheight=' .. height) -- Avoid moving the cursor with 'splitkeep' = "screen", and altering the user
-- configured value with noautocmd.
vim._with({ noautocmd = true, o = { splitkeep = 'screen' } }, function()
vim.o.cmdheight = height
end)
ext.msg.set_pos() ext.msg.set_pos()
end end
end end
@@ -47,10 +52,10 @@ end
---@param firstc string ---@param firstc string
---@param prompt string ---@param prompt string
---@param indent integer ---@param indent integer
--@param level integer ---@param level integer
---@param hl_id integer ---@param hl_id integer
function M.cmdline_show(content, pos, firstc, prompt, indent, _, hl_id) function M.cmdline_show(content, pos, firstc, prompt, indent, level, hl_id)
M.indent, M.prompt = indent, #prompt > 0 M.level, M.indent, M.prompt = level, indent, #prompt > 0
-- Only enable TS highlighter for Ex commands (not search or filter commands). -- Only enable TS highlighter for Ex commands (not search or filter commands).
M.highlighter.active[ext.bufs.cmd] = firstc == ':' and M.highlighter or nil M.highlighter.active[ext.bufs.cmd] = firstc == ':' and M.highlighter or nil
set_text(content, ('%s%s%s'):format(firstc, prompt, (' '):rep(indent))) set_text(content, ('%s%s%s'):format(firstc, prompt, (' '):rep(indent)))
@@ -127,7 +132,7 @@ function M.cmdline_hide(_, abort)
end) end)
end end
M.prompt, curpos[1], curpos[2] = false, 0, 0 M.prompt, M.level, curpos[1], curpos[2] = false, -1, 0, 0
win_config(ext.wins[ext.tab].cmd, true, ext.cmdheight) win_config(ext.wins[ext.tab].cmd, true, ext.cmdheight)
end end

View File

@@ -331,7 +331,7 @@ function M.msg_clear() end
--- ---
---@param content MsgContent ---@param content MsgContent
function M.msg_showmode(content) function M.msg_showmode(content)
M.virt.last[M.virt.idx.mode] = content M.virt.last[M.virt.idx.mode] = ext.cmd.level < 0 and content or {}
M.virt.last[M.virt.idx.search] = {} M.virt.last[M.virt.idx.search] = {}
set_virttext('last') set_virttext('last')
end end
@@ -386,7 +386,6 @@ function M.set_pos(type)
height = height, height = height,
row = win == ext.wins[ext.tab].box and 0 or 1, row = win == ext.wins[ext.tab].box and 0 or 1,
col = 10000, col = 10000,
zindex = type == 'more' and 299 or nil,
}) })
if type == 'box' then if type == 'box' then
-- Ensure last line is visible and first line is at top of window. -- Ensure last line is visible and first line is at top of window.

View File

@@ -29,7 +29,6 @@ local wincfg = { -- Default cfg for nvim_open_win().
width = 10000, width = 10000,
height = 1, height = 1,
noautocmd = true, noautocmd = true,
zindex = 300,
} }
--- Ensure the various buffers and windows have not been deleted. --- Ensure the various buffers and windows have not been deleted.
@@ -63,6 +62,8 @@ function M.tab_check_wins()
hide = type ~= 'cmd' or M.cmdheight == 0 or nil, hide = type ~= 'cmd' or M.cmdheight == 0 or nil,
title = type == 'more' and 'Messages' or nil, title = type == 'more' and 'Messages' or nil,
border = type == 'box' and not o.termguicolors and 'single' or border or 'none', border = type == 'box' and not o.termguicolors and 'single' or border or 'none',
-- kZIndexMessages < zindex < kZIndexCmdlinePopupMenu (grid_defs.h), 'more' below others.
zindex = 200 - (type == 'more' and 1 or 0),
_cmdline_offset = type == 'cmd' and 0 or nil, _cmdline_offset = type == 'cmd' and 0 or nil,
}) })
M.wins[M.tab][type] = api.nvim_open_win(M.bufs[type], false, cfg) M.wins[M.tab][type] = api.nvim_open_win(M.bufs[type], false, cfg)