vim-patch:9.1.1621: flicker in popup menu during cmdline autocompletion

Problem:  When the popup menu (PUM) occupies more than half the screen
          height, it flickers whenever a character is typed or erased.
          This happens because the PUM is cleared and the screen is
          redrawn before a new PUM is rendered. The extra redraw between
          menu updates causes visible flicker.
Solution: A complete, non-hacky fix would require removing the
          CmdlineChanged event from the loop and letting autocompletion
          manage the process end-to-end. This is because screen redraws
          after any cmdline change are necessary for other features to
          work.
          This change modifies wildtrigger() so that the next typed
          character defers the screen update instead of redrawing
          immediately. This removes the intermediate redraw, eliminating
          flicker and making cmdline autocompletion feel smooth
          (Girish Palya).

Trade-offs:
This behavior change in wildtrigger() is tailored specifically for
:h cmdline-autocompletion. wildtrigger() now has no general-purpose use
outside this scenario.

closes: vim/vim#17932

da9c966893

Use pum_check_clear() instead of update_screen().
Cherry-pick Test_wildtrigger_update_screen() change from patch 9.1.1682.

Co-authored-by: Girish Palya <girishji@gmail.com>
This commit is contained in:
zeertzjq
2025-09-19 08:52:56 +08:00
parent c2c33249a7
commit dd306bd48a
4 changed files with 117 additions and 8 deletions

View File

@@ -531,6 +531,62 @@ describe('cmdline', function()
]])
end)
-- oldtest: Test_wildtrigger_update_screen()
it('pum by wildtrigger() avoids flicker', function()
local screen = Screen.new(40, 10)
exec([[
command! -nargs=* -complete=customlist,TestFn TestCmd echo
func TestFn(cmdarg, b, c)
if a:cmdarg == 'ax'
return []
else
return map(range(1, 5), 'printf("abc%d", v:val)')
endif
endfunc
set wildmode=noselect,full
set wildoptions=pum
set wildmenu
cnoremap <F8> <C-R>=wildtrigger()[-1]<CR>
]])
feed(':TestCmd a<F8>')
screen:expect([[
|
{1:~ }|*3
{1:~ }{4: abc1 }{1: }|
{1:~ }{4: abc2 }{1: }|
{1:~ }{4: abc3 }{1: }|
{1:~ }{4: abc4 }{1: }|
{1:~ }{4: abc5 }{1: }|
:TestCmd a^ |
]])
-- Typing a character when pum is open does not close the pum window
-- This is needed to prevent pum window from flickering during
-- ':h cmdline-autocompletion'.
feed('x')
screen:expect([[
|
{1:~ }|*3
{1:~ }{4: abc1 }{1: }|
{1:~ }{4: abc2 }{1: }|
{1:~ }{4: abc3 }{1: }|
{1:~ }{4: abc4 }{1: }|
{1:~ }{4: abc5 }{1: }|
:TestCmd ax^ |
]])
-- pum window is closed when no completion candidates are available
feed('<F8>')
screen:expect([[
|
{1:~ }|*8
:TestCmd ax^ |
]])
feed('<esc>')
end)
-- oldtest: Test_long_line_noselect()
it("long line is shown properly with noselect in 'wildmode'", function()
local screen = Screen.new(60, 8)