From fcc391d89a2a30b02c3ba25a6351d37cdcd79e12 Mon Sep 17 00:00:00 2001 From: Sébastien Hoffmann Date: Sun, 5 Jul 2026 11:06:46 +0200 Subject: fix(ui2): clear showcmd virt_text together with search count Problem: when the search count is displayed, the showcmd virt_text is set to 11 empty spaces to ensure a consistent distance between search count and ruler, or screen edge in case of noruler. But when the search count is removed to make place for a message, the empty dummy showcmd remains and unnecessarily erases part of the message. Solution: properly remove showcmd together with search count. --- runtime/lua/vim/_core/ui2/messages.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim/_core') diff --git a/runtime/lua/vim/_core/ui2/messages.lua b/runtime/lua/vim/_core/ui2/messages.lua index 07dc9c205a..1961084c38 100644 --- a/runtime/lua/vim/_core/ui2/messages.lua +++ b/runtime/lua/vim/_core/ui2/messages.lua @@ -462,6 +462,7 @@ function M.msg_show(kind, content, replace_last, _, append, id, trigger) M.cmd.last_emsg = (kind == 'emsg' or kind == 'wmsg') and os.time() or M.cmd.last_emsg -- Should clear the search count now, mark itself is cleared by invalidate. M.virt.last[M.virt.idx.search][1] = nil + M.virt.last[M.virt.idx.cmd] = {} end -- When message was emitted below an already expanded cmdline, move and route to pager. tgt = ui.cmd.expand > 0 and 'pager' or tgt -- cgit From 2473cb62b7f4d77e2691d5040e06a2a61ab34462 Mon Sep 17 00:00:00 2001 From: Sébastien Hoffmann Date: Sun, 5 Jul 2026 13:55:22 +0200 Subject: fix(ui2): correctly crop message at multibyte/multicell character --- runtime/lua/vim/_core/ui2/messages.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/_core') diff --git a/runtime/lua/vim/_core/ui2/messages.lua b/runtime/lua/vim/_core/ui2/messages.lua index 1961084c38..4182fd573b 100644 --- a/runtime/lua/vim/_core/ui2/messages.lua +++ b/runtime/lua/vim/_core/ui2/messages.lua @@ -126,7 +126,7 @@ local function set_virttext(type, tgt) }) local row = texth.end_row local col = fn.virtcol2col(win, row + 1, texth.end_vcol) - local scol = fn.screenpos(win, row + 1, col).col ---@type integer + local scol = fn.screenpos(win, row + 1, col).endcol ---@type integer if type ~= 'last' then -- Calculate at which column to place the virt_text such that it is at the end @@ -179,7 +179,8 @@ local function set_virttext(type, tgt) -- Crop text on last screen row and find byte offset to place mark at. local vcol = texth.end_vcol - (scol - M.cmd.last_col) - col = vcol <= 0 and 0 or fn.virtcol2col(win, row + 1, vcol) + col = vcol <= 0 and 0 or fn.virtcol2col(win, row + 1, vcol + 1) - 1 + scol = fn.screenpos(win, row + 1, col).endcol M.cmd.prev_msg = mode > 0 and '' or M.cmd.prev_msg M.virt.cmd = mode > 0 and { {}, {} } or M.virt.cmd api.nvim_buf_set_text(ui.bufs.cmd, row, col, row, -1, { mode > 0 and ' ' or '' }) -- cgit From 0ffd74ae85bf9c6c41c904775ec6ec6d8a3eebb6 Mon Sep 17 00:00:00 2001 From: Sébastien Hoffmann Date: Sat, 11 Jul 2026 16:38:12 +0200 Subject: fix(ui2): fix ruler on repeated messages Problem: a long message is cropped to keep the ruler visible. But when the message is repeated, it can be written over the ruler, while the repetition indicator "(1)" is still placed just before the ruler, which ends up somewhere inside the message. Solution: currently, long messages are only cropped when setting the 'last' virttext. Make sure this happens after a repeated long message. --- runtime/lua/vim/_core/ui2/messages.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'runtime/lua/vim/_core') diff --git a/runtime/lua/vim/_core/ui2/messages.lua b/runtime/lua/vim/_core/ui2/messages.lua index 4182fd573b..7a6bd6e4c0 100644 --- a/runtime/lua/vim/_core/ui2/messages.lua +++ b/runtime/lua/vim/_core/ui2/messages.lua @@ -390,6 +390,13 @@ function M.show_msg(tgt, kind, content, replace_last, append, id) M.virt[tgt][M.virt.idx.dupe][1] = dupe > 0 and { 0, ('(%d)'):format(dupe) } or nil M.virt[tgt][M.virt.idx.spill][1] = tgt == 'cmd' and M.virt.cmd[M.virt.idx.spill][1] or nil set_virttext(tgt --[[@as 'cmd'|'msg']], tgt) + if tgt == 'cmd' then + -- make sure repeated long messages are cropped to keep the ruler intact + -- (if this is not scheduled, it breaks messages during textlock) + vim.schedule(function() + set_virttext('last', 'cmd') + end) + end end -- Reset message state the next event loop iteration. -- cgit