fix(ui2): dialog messages offset by the pager line count #41839

Problem:
expand_msg() derives its start row from the pager buffer even when the
target is the cmd or dialog buffer, so the copied lines are appended
instead of replacing, and the copied extmarks are placed at pager rows in
a smaller buffer: "Invalid 'end_col': out of range", thrown inside a UI
event handler.

Solution:
Offset only when appending to a visible pager, and read the line count
after msg_clear(), whose autocmds may write to the pager. Copy marks with
`strict = false`, since the rows and columns are recomputed for a
different buffer and should clamp rather than raise.

AI-assisted
This commit is contained in:
Justin M. Keyes
2026-09-11 01:01:16 -04:00
committed by GitHub
parent ce5dc72a23
commit 28ff47b8a4
2 changed files with 21 additions and 2 deletions

View File

@@ -228,7 +228,7 @@ local function pager_shown()
return api.nvim_win_is_valid(ui.wins.pager) and not api.nvim_win_get_config(ui.wins.pager).hide
end
local hlopts = { undo_restore = false, invalidate = true, priority = 1 }
local hlopts = { undo_restore = false, invalidate = true, priority = 1, strict = false }
--- Move messages to expanded cmdline, dialog or pager to show in full.
--- Return updated target+buffer in case it differs from 'src'.
---
@@ -240,7 +240,6 @@ function M.expand_msg(src, tgt, focus)
local hidden = not pager_shown()
tgt = tgt or not hidden and 'pager' or 'cmd' ---@type 'cmd'|'dialog'|'msg'|'pager'
if tgt ~= src then
local srow = hidden and 0 or api.nvim_buf_line_count(ui.bufs.pager)
local opts = { details = true, type = 'highlight' }
local marks = api.nvim_buf_get_extmarks(ui.bufs[src], -1, 0, -1, opts)
local lines = api.nvim_buf_get_lines(ui.bufs[src], 0, -1, false)
@@ -252,6 +251,8 @@ function M.expand_msg(src, tgt, focus)
M.virt[src] = { {}, {} }
end
-- Append to visible pager, replace any other target. msg_clear() events may have edited pager.
local srow = (not hidden and tgt == 'pager') and api.nvim_buf_line_count(ui.bufs.pager) or 0
api.nvim_buf_set_lines(ui.bufs[tgt], srow, -1, false, lines)
for _, m in ipairs(marks) do
hlopts.hl_group, hlopts.end_col, hlopts.end_row =

View File

@@ -1450,5 +1450,23 @@ describe('messages2', function()
{9:de} |
|
]])
-- A prompt with pending cmd messages moves them to the dialog (cmdline.lua). The pager is
-- still shown, but its line count must not offset the marks copied into the dialog.
exec_lua(function()
local ui = require('vim._core.ui2')
vim.api.nvim_buf_set_lines(ui.bufs.cmd, 0, -1, false, { 'err' })
local o = { end_row = 0, end_col = 3, hl_group = 'ErrorMsg' }
vim.api.nvim_buf_set_extmark(ui.bufs.cmd, ui.ns, 0, 0, o)
ui.msg.expand_msg('cmd', 'dialog')
end)
screen:expect([[
|
{1:~ }|*9
{3: }|
{3:^ }|
{9:err} |
|
]])
end)
end)