neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 0712a9c87bfe1ce08ae95a0cb30e5857c28e861c
parent a9271f927ff60cadf91bb17286698ceb26eeaa44
Author: glepnir <glephunter@gmail.com>
Date:   Tue, 20 Jan 2026 11:39:48 +0800

fix(pum): separate scrollbar from shadow border (#37448)

Problem:
With shadow border, scrollbar and border overlap. Shadow's right border
starts from the second row (offset by 1), but scrollbar renders on every
row including the first. If they share a column, the first row shows
scrollbar where shadow hasn't started yet, causing misalignment.

Solution:
Separate scrollbar from the shadow's right border.
Diffstat:
Msrc/nvim/popupmenu.c | 8+++++---
Mtest/functional/ui/popupmenu_spec.lua | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c @@ -643,7 +643,7 @@ void pum_redraw(void) } } - if (pum_scrollbar > 0 && !fconfig.border) { + if (pum_scrollbar > 0 && (!fconfig.border || fconfig.shadow)) { grid_width++; if (pum_rl) { col_off++; @@ -917,8 +917,10 @@ void pum_redraw(void) if (pum_scrollbar > 0) { bool thumb = i >= thumb_pos && i < thumb_pos + thumb_height; int scrollbar_col = col_off + (pum_rl ? -pum_width : pum_width); - grid_line_put_schar(scrollbar_col, (has_border && !thumb) ? border_char : fill_char, - thumb ? attr_thumb : (has_border ? border_attr : attr_scroll)); + bool use_border_style = has_border && !fconfig.shadow; + grid_line_put_schar(scrollbar_col, + (use_border_style && !thumb) ? border_char : fill_char, + thumb ? attr_thumb : (use_border_style ? border_attr : attr_scroll)); } grid_line_flush(); row++; diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua @@ -9286,6 +9286,57 @@ describe('builtin popupmenu', function() {5:-- }{6:match 1 of 3} | ]]) end + command('set pumheight=2') + feed('<C-x><C-O>') + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:------------------------------]|*10 + [3:------------------------------]| + ## grid 2 + oneone^ | + line1 | + line2line2line2line2 | + line3 | + line4line4line4 | + line5line5 | + {1:~ }|*4 + ## grid 3 + {5:-- }{6:match 1 of 3} | + ## grid 4 + {n:1info}| + ## grid 5 + {12: one }{c: }{114: }| + {n: two }{12: }{115: }| + {114: }{115: }| + ]], + win_pos = { + [2] = { + height = 10, + startcol = 0, + startrow = 0, + width = 30, + win = 1000, + }, + }, + float_pos = { + [5] = { -1, 'NW', 2, 1, 2, false, 100, 2, 1, 2 }, + [4] = { 1001, 'NW', 1, 1, 19, false, 50, 1, 1, 19 }, + }, + }) + else + screen:expect([[ + oneone^ | + li{12: one }{c: }{116: }{n:info} | + li{n: two }{12: }{117:2} | + li{116:n}{117:e3 } | + line4line4line4 | + line5line5 | + {1:~ }|*4 + {5:-- }{6:match 1 of 3} | + ]]) + end end) it("'pumborder' with none #36207", function() command('set wildoptions=pum pumborder=none')