fix(ui2): correctly crop message at multibyte/multicell character

This commit is contained in:
Sébastien Hoffmann
2026-07-05 13:55:22 +02:00
parent fcc391d89a
commit 2473cb62b7
2 changed files with 93 additions and 2 deletions

View File

@@ -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 '' })

View File

@@ -1118,4 +1118,94 @@ describe('messages2', function()
-----------------------------------1,1 All|
]])
end)
it('crops long messages to make place for ruler', function()
command('set noruler | echo "-"->repeat(&columns)')
screen:expect([[
^ |
{1:~ }|*12
-----------------------------------------------------|
]])
feed('<C-L>')
command('set ruler showcmd | echo "-"->repeat(&columns)')
screen:expect([[
^ |
{1:~ }|*12
-----------------------------------0,0-1 All|
]])
feed('<C-L>')
-- message with multibyte characters
command('echo "∙"->repeat(&columns)')
screen:expect([[
^ |
{1:~ }|*12
∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙0,0-1 All|
]])
feed('<C-L>')
-- message with multicell characters
command('echo "-".."🙂"->repeat(&columns/2-1)')
screen:expect([[
^ |
{1:~ }|*12
-🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂0,0-1 All|
]])
feed('<C-L>')
command('echo "🙂"->repeat(&columns/2)')
screen:expect([[
^ |
{1:~ }|*12
🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂🙂 0,0-1 All|
]])
feed('<C-L>')
-- when cmdheight>1, only the last line is cropped
command('set cmdheight=2 | redraw | echo "-"->repeat(2*&columns)')
screen:expect([[
^ |
{1:~ }|*11
-----------------------------------------------------|
-----------------------------------0,0-1 All|
]])
feed('<C-L>')
command('set cmdheight=2 showbreak=> | redraw | echo "-"->repeat(2*&columns-1)')
screen:expect([[
^ |
{1:~ }|*11
-----------------------------------------------------|
{1:>}----------------------------------0,0-1 All|
]])
command('set showbreak&')
feed('<C-L>')
-- ruler is not shown after dismissing expanded cmdline with key press -> no need to crop
command('set cmdheight=1 | redraw | echo "-"->repeat(2*&columns)')
feed('k')
screen:expect([[
^ |
{1:~ }|*12
-----------------------------------------------------|
]])
feed('<C-L>')
-- messages are deferred until showcmd is cleared -> no need to crop for showcmd
command('lua vim.defer_fn(function() vim.cmd[[echo "-"->repeat(&columns)]] end, 50)')
feed('g')
screen:expect([[
^ |
{1:~ }|*12
g 0,0-1 All|
]])
screen:sleep(100)
feed('<Esc>')
screen:expect([[
^ |
{1:~ }|*12
-----------------------------------0,0-1 All|
]])
feed('<C-L>')
-- when the ruler is configured smaller, there is more space for messages
command('set rulerformat=%l | redraw | echo "-"->repeat(&columns)')
screen:expect([[
^ |
{1:~ }|*12
----------------------------------------------------0|
]])
end)
end)