commit 5a6532168443e479143c84aa42a5ac17d4c5db63
parent 41068c77aa1b221bc4f4321ac0dfe55e13a9f27f
Author: glepnir <glephunter@gmail.com>
Date: Sun, 18 Jan 2026 16:55:30 +0800
fix(pum): text overflows into border on truncation (#37438)
Problem:
When text is too long, it overflows into the border. This happens because
grid_line_maxcol includes border columns, so grid_line_puts can write
there.
Solution:
Truncate string to available width when need_fcs_trunc is set.
Diffstat:
2 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
@@ -817,6 +817,23 @@ void pum_redraw(void)
if (width_limit - totwidth < cells + pad) {
need_fcs_trunc = true;
}
+ if (need_fcs_trunc) {
+ int available_cells = width_limit - totwidth;
+ // Find the truncation point by counting display cells
+ char *p_end = st;
+ int displayed = 0;
+ while (*p_end != NUL) {
+ int char_cells = utf_ptr2cells(p_end);
+ if (displayed + char_cells > available_cells) {
+ break;
+ }
+ displayed += char_cells;
+ MB_PTR_ADV(p_end);
+ }
+ *p_end = NUL;
+ cells = displayed;
+ width = displayed;
+ }
if (attrs == NULL) {
grid_line_puts(grid_col, st, -1, attr);
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
@@ -9405,6 +9405,45 @@ describe('builtin popupmenu', function()
assert_alive()
eq({ 4, 1 }, { #fn.complete_info({ 'items' }).items, fn.pumvisible() })
end)
+
+ it("works with 'pummaxwidth' #test", function()
+ exec([[
+ set pummaxwidth=10
+ set cot+=menuone
+ let g:list = [#{word: repeat('fo', 10)}]
+ ]])
+ feed('S<C-x><C-o>')
+ if multigrid then
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:------------------------------]|*10
+ [3:------------------------------]|
+ ## grid 2
+ fofofofofofofofofofo^ |
+ {1:~ }|*9
+ ## grid 3
+ {5:-- The only match} |
+ ## grid 4
+ ╭──────────╮|
+ │{12:fofofofof>}│|
+ ╰──────────╯|
+ ]],
+ float_pos = {
+ [4] = { -1, 'NW', 2, 1, 0, false, 100, 1, 1, 0 },
+ },
+ })
+ else
+ screen:expect([[
+ fofofofofofofofofofo^ |
+ ╭──────────╮{1: }|
+ │{12:fofofofof>}│{1: }|
+ ╰──────────╯{1: }|
+ {1:~ }|*6
+ {5:-- The only match} |
+ ]])
+ end
+ end)
end)
end