mirror of
https://github.com/neovim/neovim.git
synced 2025-10-21 17:21:49 +00:00
fix(extui): only append messages exceeding 'cmdheight' to "more"
Problem: 8defe1a
declared the "more" window the most convenient place to
route messages to if it is already open for msg.pos == 'cmd'.
In usage, this doesn't appear to be the case. Appending messages
as added in that commit is still useful, but should only be done
for messages that spill 'cmdheight'.
Solution: Only append messages exceeding 'cmdheight' to the more window.
To do this, instead of immediately writing to the more buffer,
write to the cmd buffer and calculate its height. Then copy the
text and its highlights to the more buffer.
This commit is contained in:
@@ -51,7 +51,7 @@ end
|
||||
---@param len integer Number of rows that should be removed.
|
||||
function M.box:start_timer(buf, len)
|
||||
self.timer = vim.defer_fn(function()
|
||||
if buf ~= ext.bufs.box or not api.nvim_buf_is_valid(buf) then
|
||||
if self.count == 0 or not api.nvim_buf_is_valid(buf) then
|
||||
return -- Messages moved to more or buffer was closed.
|
||||
end
|
||||
api.nvim_buf_set_lines(buf, 0, len, false, {})
|
||||
@@ -172,18 +172,36 @@ local function set_virttext(type)
|
||||
end
|
||||
end
|
||||
|
||||
--- Move message buffer to more window.
|
||||
local function msg_to_more(tar)
|
||||
api.nvim_buf_delete(ext.bufs.more, { force = true })
|
||||
api.nvim_buf_set_name(ext.bufs[tar], 'vim._extui.more')
|
||||
ext.bufs.more, ext.bufs[tar], M[tar].count = ext.bufs[tar], -1, 0
|
||||
ext.tab_check_wins() -- Create and setup new/moved buffer.
|
||||
M.set_pos('more')
|
||||
end
|
||||
|
||||
-- We need to keep track of the current message column to be able to
|
||||
-- append or overwrite messages for :echon or carriage returns.
|
||||
local col = 0
|
||||
local col, will_more, hlopts = 0, false, { undo_restore = false, invalidate = true, priority = 1 }
|
||||
--- Move message to more buffer, appending if window was already open.
|
||||
local function msg_to_more(tar)
|
||||
if will_more then
|
||||
return
|
||||
end
|
||||
will_more, M.prev_msg = true, ''
|
||||
|
||||
vim.schedule(function()
|
||||
local hidden = api.nvim_win_get_config(ext.wins.more).hide
|
||||
local marks = api.nvim_buf_get_extmarks(ext.bufs[tar], -1, 0, -1, { details = true })
|
||||
local lines = api.nvim_buf_get_lines(ext.bufs[tar], 0, -1, false)
|
||||
api.nvim_buf_set_lines(ext.bufs.more, hidden and 0 or -1, -1, false, lines)
|
||||
local rows = api.nvim_buf_line_count(ext.bufs.more) - #lines
|
||||
api.nvim_buf_set_lines(ext.bufs[tar], 0, -1, false, {})
|
||||
for _, mark in ipairs(marks) do
|
||||
hlopts.end_col, hlopts.hl_group = mark[4].end_col, mark[4].hl_group
|
||||
api.nvim_buf_set_extmark(ext.bufs.more, ext.ns, mark[2] + rows, mark[3], hlopts)
|
||||
end
|
||||
M.box:close()
|
||||
M.set_pos('more')
|
||||
if not hidden then
|
||||
api.nvim_command('norm! G')
|
||||
end
|
||||
M[tar].count, col, will_more = 0, 0, false
|
||||
end)
|
||||
end
|
||||
|
||||
---@param tar 'box'|'cmd'|'more'|'prompt'
|
||||
---@param content MsgContent
|
||||
---@param replace_last boolean
|
||||
@@ -215,14 +233,14 @@ function M.show_msg(tar, content, replace_last, append, more)
|
||||
local line_count = api.nvim_buf_line_count(ext.bufs[tar])
|
||||
---@type integer Start row after last line in the target buffer, unless
|
||||
---this is the first message, or in case of a repeated or replaced message.
|
||||
local row = M[tar] and count <= 1 and (tar == 'cmd' and ext.cmd.row or 0)
|
||||
local row = M[tar] and count <= 1 and not will_more and (tar == 'cmd' and ext.cmd.row or 0)
|
||||
or line_count - ((replace_last or restart or cr or append) and 1 or 0)
|
||||
local curline = (cr or append) and api.nvim_buf_get_lines(ext.bufs[tar], row, row + 1, false)[1]
|
||||
local start_row, width = row, M.box.width
|
||||
col = append and not cr and math.min(col, #curline) or 0
|
||||
|
||||
-- Accumulate to be inserted and highlighted message chunks for a non-repeated message.
|
||||
for _, chunk in ipairs((M[tar] or dupe == 0) and content or {}) do
|
||||
for _, chunk in ipairs((not M[tar] or dupe == 0) and content or {}) do
|
||||
-- Split at newline and write to start of line after carriage return.
|
||||
for str in (chunk[2] .. '\0'):gmatch('.-[\n\r%z]') do
|
||||
local repl, pat = str:sub(1, -2), str:sub(-1)
|
||||
@@ -239,13 +257,8 @@ function M.show_msg(tar, content, replace_last, append, more)
|
||||
width = tar == 'box' and math.max(width, api.nvim_strwidth(curline)) or 0
|
||||
|
||||
if chunk[3] > 0 then
|
||||
api.nvim_buf_set_extmark(ext.bufs[tar], ext.ns, row, col, {
|
||||
end_col = end_col,
|
||||
hl_group = chunk[3],
|
||||
undo_restore = false,
|
||||
invalidate = true,
|
||||
priority = 1,
|
||||
})
|
||||
hlopts.end_col, hlopts.hl_group = end_col, chunk[3]
|
||||
api.nvim_buf_set_extmark(ext.bufs[tar], ext.ns, row, col, hlopts)
|
||||
end
|
||||
|
||||
if pat == '\n' then
|
||||
@@ -261,7 +274,6 @@ function M.show_msg(tar, content, replace_last, append, more)
|
||||
local h = api.nvim_win_text_height(ext.wins.box, { start_row = start_row })
|
||||
if more and h.all > 1 then
|
||||
msg_to_more(tar)
|
||||
M.box:close()
|
||||
return
|
||||
end
|
||||
|
||||
@@ -284,8 +296,7 @@ function M.show_msg(tar, content, replace_last, append, more)
|
||||
api.nvim__redraw({ flush = true, cursor = true, win = ext.wins.cmd })
|
||||
else
|
||||
local h = api.nvim_win_text_height(ext.wins.cmd, {})
|
||||
if more and h.all > ext.cmdheight then
|
||||
ext.cmd.highlighter:destroy()
|
||||
if (more or not api.nvim_win_get_config(ext.wins.cmd).hide) and h.all > ext.cmdheight then
|
||||
msg_to_more(tar)
|
||||
return
|
||||
end
|
||||
@@ -341,10 +352,6 @@ function M.msg_show(kind, content, _, _, append)
|
||||
-- Verbose messages are sent too often to be meaningful in the cmdline:
|
||||
-- always route to box regardless of cfg.msg.pos.
|
||||
M.show_msg('box', content, false, append)
|
||||
elseif ext.cfg.msg.pos == 'cmd' and not api.nvim_win_get_config(ext.wins.more).hide then
|
||||
-- Append message to already open 'more' window.
|
||||
M.msg_history_show({ { 'spill', content } })
|
||||
api.nvim_command('norm! G')
|
||||
elseif ext.cmd.prompt then
|
||||
-- Route to prompt that stays open so long as the cmdline prompt is active.
|
||||
api.nvim_buf_set_lines(ext.bufs.prompt, 0, -1, false, { '' })
|
||||
@@ -360,7 +367,9 @@ function M.msg_show(kind, content, _, _, append)
|
||||
-- Store the time when an error message was emitted in order to not overwrite
|
||||
-- it with 'last' virt_text in the cmdline to give the user a chance to read it.
|
||||
M.cmd.last_emsg = kind == 'emsg' and os.time() or M.cmd.last_emsg
|
||||
-- Should clear the search count now, which also affects the showcmd position.
|
||||
M.virt.last[M.virt.idx.search][1] = nil
|
||||
M.msg_showcmd({})
|
||||
end
|
||||
|
||||
-- Typed "inspection" messages should be routed to the more window.
|
||||
@@ -406,7 +415,7 @@ function M.msg_ruler(content)
|
||||
end
|
||||
|
||||
---@alias MsgHistory [string, MsgContent]
|
||||
--- Zoom in on the message window with the message history.
|
||||
--- Open the message history in the more window.
|
||||
---
|
||||
---@param entries MsgHistory[]
|
||||
function M.msg_history_show(entries)
|
||||
@@ -414,14 +423,9 @@ function M.msg_history_show(entries)
|
||||
return
|
||||
end
|
||||
|
||||
-- Appending messages while 'more' window is open.
|
||||
local clear = entries[1][1] ~= 'spill' or api.nvim_win_get_config(ext.wins.more).hide == true
|
||||
if clear then
|
||||
api.nvim_buf_set_lines(ext.bufs.more, 0, -1, false, {})
|
||||
end
|
||||
|
||||
api.nvim_buf_set_lines(ext.bufs.more, 0, -1, false, {})
|
||||
for i, entry in ipairs(entries) do
|
||||
M.show_msg('more', entry[2], i == 1 and clear, false)
|
||||
M.show_msg('more', entry[2], i == 1, false)
|
||||
end
|
||||
|
||||
M.set_pos('more')
|
||||
|
@@ -77,7 +77,7 @@ function M.tab_check_wins()
|
||||
end
|
||||
|
||||
if setopt then
|
||||
api.nvim_buf_set_name(M.bufs[type], 'vim._extui.' .. type)
|
||||
api.nvim_buf_set_name(M.bufs[type], 'nvim.' .. type)
|
||||
if type == 'more' then
|
||||
-- Close more window with `q`, same as `checkhealth`
|
||||
api.nvim_buf_set_keymap(M.bufs.more, 'n', 'q', '<Cmd>wincmd c<CR>', {})
|
||||
|
Reference in New Issue
Block a user