mirror of
https://github.com/neovim/neovim.git
synced 2026-03-27 19:02:02 +00:00
fix(ui2): show messages in dialog window when entering expanded cmdline #38465
Problem: - With expanded messages exceeding cfg.msg.cmd.height, entering
the cmdline scrolls to the bottom and expands to the full "cmd"
buffer text height.
- Cursor in the pager is not always at the last message and at
the bottom of the window when appending to the pager.
- unreliable test: messages2_spec: "closed msg window timer removes
empty lines".
Solution: - Achieve separation of the cmdline and message text by moving
messages to the dialog window when entering the cmdline below
expanded messages.
- Set cursor to start of the first message only when first
entering the pager. Use `norm! zb` to position last message
at the bottom of the window (which shouldn't crash anymore
since 911337eb).
- Increase cfg.msg.msg.timeout used in the test file.
This commit is contained in:
@@ -92,10 +92,11 @@ end
|
||||
---@param level integer
|
||||
---@param hl_id integer
|
||||
function M.cmdline_show(content, pos, firstc, prompt, indent, level, hl_id)
|
||||
-- When entering the cmdline while it is expanded, place cmdline below messages.
|
||||
-- When entering the cmdline while it is expanded, move messages to dialog window.
|
||||
if M.level == 0 and ui.msg.cmd_on_key then
|
||||
M.srow = api.nvim_buf_line_count(ui.bufs.cmd)
|
||||
M.expand, ui.msg.cmd_on_key = 1, nil
|
||||
M.expand, M.dialog, ui.msg.cmd_on_key = 1, true, nil
|
||||
api.nvim_win_set_config(ui.wins.cmd, { border = 'none' })
|
||||
ui.msg.expand_msg('cmd')
|
||||
elseif ui.msg.cmd.msg_row ~= -1 and M.expand == 0 then
|
||||
ui.msg.msg_clear()
|
||||
end
|
||||
|
||||
@@ -191,13 +191,13 @@ local function set_virttext(type, tgt)
|
||||
end
|
||||
|
||||
local hlopts = { undo_restore = false, invalidate = true, priority = 1 }
|
||||
--- Move messages to expanded cmdline or pager to show in full.
|
||||
local function expand_msg(src)
|
||||
--- Move messages to expanded cmdline, dialog or pager to show in full.
|
||||
function M.expand_msg(src)
|
||||
-- Copy and clear message from src to enlarged cmdline that is dismissed by any
|
||||
-- key press. Append to pager instead if it isn't hidden or we want to enter it
|
||||
-- after cmdline was entered during expanded cmdline.
|
||||
local hidden = api.nvim_win_get_config(ui.wins.pager).hide
|
||||
local tgt = (ui.cmd.expand > 0 or not hidden) and 'pager' or 'cmd'
|
||||
local tgt = (src == 'dialog' or not hidden) and 'pager' or ui.cmd.expand > 0 and 'dialog' or 'cmd'
|
||||
if tgt ~= src then
|
||||
local srow = hidden and 0 or api.nvim_buf_line_count(ui.bufs.pager)
|
||||
local opts = { details = true, type = 'highlight' }
|
||||
@@ -322,17 +322,16 @@ function M.show_msg(tgt, kind, content, replace_last, append, id)
|
||||
api.nvim_win_set_width(ui.wins.msg, width)
|
||||
local texth = api.nvim_win_text_height(ui.wins.msg, { start_row = start_row, end_row = row })
|
||||
if texth.all > math.ceil(o.lines * 0.5) then
|
||||
expand_msg(tgt)
|
||||
M.expand_msg(tgt)
|
||||
else
|
||||
M.msg.width = width
|
||||
M.msg:start_timer(buf, id)
|
||||
end
|
||||
elseif tgt == 'cmd' and dupe == 0 then
|
||||
fn.clearmatches(ui.wins.cmd) -- Clear matchparen highlights.
|
||||
if ui.cmd.srow > 0 and ui.cmd.expand == 0 then
|
||||
if ui.cmd.srow > 0 then
|
||||
-- In block mode the cmdheight is already dynamic, so just print the full message
|
||||
-- regardless of height. Put cmdline below message. Don't do this if the block mode
|
||||
-- was simulated for a cmdline entered while expanded, will open pager instead.
|
||||
-- regardless of height. Put cmdline below message.
|
||||
ui.cmd.srow = row + 1
|
||||
else
|
||||
api.nvim_win_set_cursor(ui.wins.cmd, { 1, 0 }) -- ensure first line is visible
|
||||
@@ -345,7 +344,7 @@ function M.show_msg(tgt, kind, content, replace_last, append, id)
|
||||
-- Expand the cmdline for a non-error message that doesn't fit.
|
||||
local error_kinds = { rpc_error = 1, emsg = 1, echoerr = 1, lua_error = 1 }
|
||||
if texth.all > ui.cmdheight and (ui.cmdheight == 0 or not error_kinds[kind]) then
|
||||
expand_msg(tgt)
|
||||
M.expand_msg(tgt)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -429,17 +428,18 @@ function M.msg_show(kind, content, replace_last, _, append, id, trigger)
|
||||
-- When message was emitted below an already expanded cmdline, move and route to pager.
|
||||
tgt = ui.cmd.expand > 0 and 'pager' or tgt
|
||||
if ui.cmd.expand == 1 then
|
||||
expand_msg('cmd')
|
||||
M.expand_msg('dialog')
|
||||
end
|
||||
ui.cmd.expand = ui.cmd.expand + (ui.cmd.expand > 0 and 1 or 0)
|
||||
|
||||
local enter_pager = tgt == 'pager' and not in_pager
|
||||
M.show_msg(tgt, kind, content, replace_last or enter_pager or ui.cmd.expand > 0, append, id)
|
||||
-- Don't remember search_cmd message as actual message.
|
||||
M.show_msg(tgt, kind, content, replace_last or enter_pager, append, id)
|
||||
if kind == 'search_cmd' then
|
||||
-- Don't remember search_cmd message as actual message.
|
||||
M.cmd.ids, M.prev_msg = {}, ''
|
||||
elseif tgt == 'pager' and in_pager and not enter_pager then
|
||||
api.nvim_win_set_cursor(ui.wins.pager, { api.nvim_buf_line_count(ui.bufs.pager), 0 })
|
||||
elseif tgt == 'pager' then
|
||||
-- Position cursor at start of first or last message at bottom of window.
|
||||
fn.win_execute(ui.wins.pager, 'norm! ' .. (enter_pager and 'gg0' or 'G0zb'))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -500,6 +500,7 @@ function M.msg_history_show(entries, prev_cmd)
|
||||
for i, entry in ipairs(entries) do
|
||||
M.show_msg('pager', entry[1], entry[2], i == 1, entry[3], 0)
|
||||
end
|
||||
api.nvim_win_set_cursor(ui.wins.pager, { 1, 0 })
|
||||
|
||||
M.set_pos('pager')
|
||||
end
|
||||
@@ -526,6 +527,7 @@ local cmd_on_key = function(_, typed)
|
||||
api.nvim_command('norm! g<')
|
||||
end
|
||||
set_virttext('msg')
|
||||
return entered and ''
|
||||
end
|
||||
|
||||
--- Add virtual [+x] text to indicate scrolling is possible.
|
||||
@@ -595,7 +597,6 @@ local function enter_pager()
|
||||
-- Cmdwin is closed one event iteration later so schedule in case it was open.
|
||||
vim.schedule(function()
|
||||
local height, id = api.nvim_win_get_height(ui.wins.pager), 0
|
||||
api.nvim_win_set_cursor(ui.wins.pager, { 1, 0 })
|
||||
api.nvim_set_option_value('eiw', '', { scope = 'local', win = ui.wins.pager })
|
||||
api.nvim_set_current_win(ui.wins.pager)
|
||||
id = api.nvim_create_autocmd({ 'WinEnter', 'CmdwinEnter', 'WinResized' }, {
|
||||
@@ -646,7 +647,7 @@ function M.set_pos(tgt)
|
||||
cfg.row, cfg.height = win_row_height(t, texth.all)
|
||||
cfg.border = t ~= 'msg' and { '', top, '', '', '', '', '', '' } or nil
|
||||
cfg.mouse = tgt == 'cmd' or nil
|
||||
cfg.title = tgt == 'dialog' and cfg.height < texth.all and { hint } or nil
|
||||
cfg.title = tgt == 'dialog' and { cfg.height < texth.all and hint or { '' } } or nil
|
||||
api.nvim_win_set_config(win, cfg)
|
||||
|
||||
if tgt == 'cmd' and not M.cmd_on_key then
|
||||
|
||||
@@ -6,7 +6,7 @@ local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local api, clear, command, exec_lua, feed = n.api, n.clear, n.command, n.exec_lua, n.feed
|
||||
|
||||
local msg_timeout = 200
|
||||
local msg_timeout = 400
|
||||
local function set_msg_target_zero_ch()
|
||||
exec_lua(function()
|
||||
require('vim._core.ui2').enable({ msg = { target = 'msg', msg = { timeout = msg_timeout } } })
|
||||
@@ -447,9 +447,9 @@ describe('messages2', function()
|
||||
foo |
|
||||
{1:~ }|*8
|
||||
{3: }|
|
||||
^foo |
|
||||
foo |
|
||||
bar |
|
||||
baz |
|
||||
^baz |
|
||||
{16::}{15:echo} {26:"baz"} |
|
||||
]])
|
||||
-- Subsequent typed commands are appended to the pager.
|
||||
|
||||
Reference in New Issue
Block a user