mirror of
https://github.com/neovim/neovim.git
synced 2026-05-02 12:04:58 +00:00
fix(ui2): wildmenu hidden behind dialog window #37684
Problem: The wildmenu is hidden behind the dialog window with "list" in 'wildmode'.
Global ('laststatus' set to 3) statusline is hidden behind the
pager window.
Solution: Check wildmenumode() to adjust the dialog position when necessary.
Ensure pager is positioned above the global statusline with 'laststus' set to 3.
This commit is contained in:
@@ -8,6 +8,7 @@ local M = {
|
|||||||
srow = 0, -- Buffer row at which the current cmdline starts; > 0 in block mode.
|
srow = 0, -- Buffer row at which the current cmdline starts; > 0 in block mode.
|
||||||
erow = 0, -- Buffer row at which the current cmdline ends; messages appended here in block mode.
|
erow = 0, -- Buffer row at which the current cmdline ends; messages appended here in block mode.
|
||||||
level = -1, -- Current cmdline level; 0 when inactive, -1 one loop iteration after closing.
|
level = -1, -- Current cmdline level; 0 when inactive, -1 one loop iteration after closing.
|
||||||
|
wmnumode = 0, -- Return value of wildmenumode(), dialog position adjusted when toggled.
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Set the 'cmdheight' and cmdline window height. Reposition message windows.
|
--- Set the 'cmdheight' and cmdline window height. Reposition message windows.
|
||||||
@@ -28,6 +29,9 @@ local function win_config(win, hide, height)
|
|||||||
vim.o.cmdheight = height
|
vim.o.cmdheight = height
|
||||||
end)
|
end)
|
||||||
ext.msg.set_pos()
|
ext.msg.set_pos()
|
||||||
|
elseif M.wmnumode ~= (M.prompt and fn.wildmenumode() or 0) then
|
||||||
|
M.wmnumode = (M.wmnumode == 1 and 0 or 1)
|
||||||
|
ext.msg.set_pos()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -469,25 +469,20 @@ end
|
|||||||
---@param type? 'cmd'|'dialog'|'msg'|'pager' Type of to be positioned window (nil for all).
|
---@param type? 'cmd'|'dialog'|'msg'|'pager' Type of to be positioned window (nil for all).
|
||||||
function M.set_pos(type)
|
function M.set_pos(type)
|
||||||
local function win_set_pos(win)
|
local function win_set_pos(win)
|
||||||
|
local cfg = { hide = false, relative = 'laststatus', col = 10000 }
|
||||||
local texth = type and api.nvim_win_text_height(win, {}) or {}
|
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().msgsep or ' ', 'MsgSeparator' }
|
local top = { vim.opt.fcs:get().msgsep or ' ', 'MsgSeparator' }
|
||||||
local border = win ~= ext.wins.msg and { '', top, '', '', '', '', '', '' } or nil
|
cfg.height = type and math.min(texth.all, math.ceil(o.lines * 0.5))
|
||||||
local config = {
|
cfg.border = win ~= ext.wins.msg and { '', top, '', '', '', '', '', '' } or nil
|
||||||
hide = false,
|
cfg.focusable = type == 'cmd' or nil
|
||||||
relative = (win == ext.wins.pager or win == ext.wins.dialog) and 'editor' or 'laststatus',
|
cfg.row = (win == ext.wins.msg and 0 or 1) - ext.cmd.wmnumode
|
||||||
border = border,
|
cfg.row = cfg.row - ((win == ext.wins.pager and o.laststatus == 3) and 1 or 0)
|
||||||
height = height,
|
api.nvim_win_set_config(win, cfg)
|
||||||
row = (win == ext.wins.pager or win == ext.wins.dialog) and o.lines - o.cmdheight or 0,
|
|
||||||
col = 10000,
|
|
||||||
focusable = type == 'cmd' or nil, -- Allow entering the cmdline window.
|
|
||||||
}
|
|
||||||
api.nvim_win_set_config(win, config)
|
|
||||||
|
|
||||||
if type == 'cmd' and not cmd_on_key then
|
if type == 'cmd' and not cmd_on_key then
|
||||||
-- Temporarily showing a full message in the cmdline, until next key press.
|
-- Temporarily showing a full message in the cmdline, until next key press.
|
||||||
local save_spill = M.virt.msg[M.virt.idx.spill][1]
|
local save_spill = M.virt.msg[M.virt.idx.spill][1]
|
||||||
local spill = texth.all > height and (' [+%d]'):format(texth.all - height)
|
local spill = texth.all > cfg.height and (' [+%d]'):format(texth.all - cfg.height)
|
||||||
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
||||||
set_virttext('msg', 'cmd')
|
set_virttext('msg', 'cmd')
|
||||||
M.virt.msg[M.virt.idx.spill][1] = save_spill
|
M.virt.msg[M.virt.idx.spill][1] = save_spill
|
||||||
@@ -554,7 +549,7 @@ function M.set_pos(type)
|
|||||||
end)
|
end)
|
||||||
elseif type == 'msg' then
|
elseif type == 'msg' 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.
|
||||||
local row = (texth.all > height and texth.end_row or 0) + 1
|
local row = (texth.all > cfg.height and texth.end_row or 0) + 1
|
||||||
api.nvim_win_set_cursor(ext.wins.msg, { row, 0 })
|
api.nvim_win_set_cursor(ext.wins.msg, { row, 0 })
|
||||||
elseif type == 'pager' then
|
elseif type == 'pager' then
|
||||||
if fn.getcmdwintype() ~= '' then
|
if fn.getcmdwintype() ~= '' then
|
||||||
@@ -571,10 +566,10 @@ function M.set_pos(type)
|
|||||||
api.nvim_create_autocmd({ 'WinEnter', 'CmdwinEnter', 'CmdwinLeave' }, {
|
api.nvim_create_autocmd({ 'WinEnter', 'CmdwinEnter', 'CmdwinLeave' }, {
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
if api.nvim_win_is_valid(ext.wins.pager) then
|
if api.nvim_win_is_valid(ext.wins.pager) then
|
||||||
local cfg = ev.event == 'CmdwinLeave' and config
|
local config = ev.event == 'CmdwinLeave' and cfg
|
||||||
or ev.event == 'WinEnter' and { hide = true }
|
or ev.event == 'WinEnter' and { hide = true }
|
||||||
or { relative = 'win', win = 0, row = 0, col = 0 }
|
or { relative = 'win', win = 0, row = 0, col = 0 }
|
||||||
api.nvim_win_set_config(ext.wins.pager, cfg)
|
api.nvim_win_set_config(ext.wins.pager, config)
|
||||||
end
|
end
|
||||||
return ev.event == 'WinEnter'
|
return ev.event == 'WinEnter'
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ local tab = 0
|
|||||||
---Ensure target buffers and windows are still valid.
|
---Ensure target buffers and windows are still valid.
|
||||||
function M.check_targets()
|
function M.check_targets()
|
||||||
local curtab = api.nvim_get_current_tabpage()
|
local curtab = api.nvim_get_current_tabpage()
|
||||||
for _, type in ipairs({ 'cmd', 'dialog', 'msg', 'pager' }) do
|
for i, type in ipairs({ 'cmd', 'dialog', 'msg', 'pager' }) do
|
||||||
local setopt = not api.nvim_buf_is_valid(M.bufs[type])
|
local setopt = not api.nvim_buf_is_valid(M.bufs[type])
|
||||||
if setopt then
|
if setopt then
|
||||||
M.bufs[type] = api.nvim_create_buf(false, false)
|
M.bufs[type] = api.nvim_create_buf(false, false)
|
||||||
@@ -50,8 +50,8 @@ function M.check_targets()
|
|||||||
anchor = type ~= 'cmd' and 'SE' or nil,
|
anchor = type ~= 'cmd' and 'SE' or nil,
|
||||||
hide = type ~= 'cmd' or M.cmdheight == 0 or nil,
|
hide = type ~= 'cmd' or M.cmdheight == 0 or nil,
|
||||||
border = type ~= 'msg' and 'none' or nil,
|
border = type ~= 'msg' and 'none' or nil,
|
||||||
-- kZIndexMessages < zindex < kZIndexCmdlinePopupMenu (grid_defs.h), pager below others.
|
-- kZIndexMessages < cmd zindex < kZIndexCmdlinePopupMenu (grid_defs.h), pager below others.
|
||||||
zindex = 200 + (type == 'cmd' and 1 or type == 'pager' and -1 or 0),
|
zindex = 201 - i,
|
||||||
_cmdline_offset = type == 'cmd' and 0 or nil,
|
_cmdline_offset = type == 'cmd' and 0 or nil,
|
||||||
})
|
})
|
||||||
if tab ~= curtab and api.nvim_win_is_valid(M.wins[type]) then
|
if tab ~= curtab and api.nvim_win_is_valid(M.wins[type]) then
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ describe('cmdline2', function()
|
|||||||
screen = Screen.new()
|
screen = Screen.new()
|
||||||
screen:add_extra_attr_ids({
|
screen:add_extra_attr_ids({
|
||||||
[100] = { foreground = Screen.colors.Magenta1, bold = true },
|
[100] = { foreground = Screen.colors.Magenta1, bold = true },
|
||||||
|
[101] = { background = Screen.colors.Yellow, foreground = Screen.colors.Grey0 },
|
||||||
})
|
})
|
||||||
exec_lua(function()
|
exec_lua(function()
|
||||||
require('vim._extui').enable({})
|
require('vim._extui').enable({})
|
||||||
@@ -180,6 +181,44 @@ describe('cmdline2', function()
|
|||||||
{16::}{15:s}{16:/f}^ |
|
{16::}{15:s}{16:/f}^ |
|
||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('dialog position is adjusted for toggled wildmenu', function()
|
||||||
|
exec([[
|
||||||
|
set wildmode=list:full,full wildoptions-=pum
|
||||||
|
func Foo()
|
||||||
|
endf
|
||||||
|
func Fooo()
|
||||||
|
endf
|
||||||
|
]])
|
||||||
|
feed(':call Fo<C-Z>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*9
|
||||||
|
{3: }|
|
||||||
|
Foo() Fooo() |
|
||||||
|
|
|
||||||
|
{16::}{15:call} Fo^ |
|
||||||
|
]])
|
||||||
|
feed('<C-Z>')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*8
|
||||||
|
{3: }|
|
||||||
|
Foo() Fooo() |
|
||||||
|
|
|
||||||
|
{101:Foo()}{3: Fooo() }|
|
||||||
|
{16::}{15:call} {25:Foo}{16:()}^ |
|
||||||
|
]])
|
||||||
|
feed('()')
|
||||||
|
screen:expect([[
|
||||||
|
|
|
||||||
|
{1:~ }|*9
|
||||||
|
{3: }|
|
||||||
|
Foo() Fooo() |
|
||||||
|
|
|
||||||
|
{16::}{15:call} {25:Foo}{16:()()}^ |
|
||||||
|
]])
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('cmdline2', function()
|
describe('cmdline2', function()
|
||||||
|
|||||||
Reference in New Issue
Block a user