neovim

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

commit 18f24b85c34a4d431bccf5ea545f8b168917fcd9
parent d784ed7013b1b244728d01d180caf2f1a974c515
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Mon,  8 Sep 2025 08:15:54 +0800

vim-patch:9.1.1740: Memory leak with wildmode=longest,full and wildoptions=pum

Problem:  Memory leak with wildmode=longest,full and wildoptions=pum
          (after 9.1.1737).
Solution: Avoid using showmatches() and WILD_NEXT together.  Also fix
          wildmode=longest,noselect:full selecting wrong item
          (zeertzjq).

fixes: vim/vim#18228
closes: vim/vim#18229

https://github.com/vim/vim/commit/c7f235bd432c0a7500ae39acdad7d63a614a1b33

Diffstat:
Msrc/nvim/ex_getln.c | 8+++-----
Mtest/functional/ui/popupmenu_spec.lua | 37+++++++++++++++++++++++++++++++++----
Mtest/old/testdir/test_cmdline.vim | 17+++++++++++++++++
3 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c @@ -1188,13 +1188,11 @@ static int command_line_wildchar_complete(CommandLineState *s) bool wim_full_next = (wim_flags[1] & kOptWimFlagFull); bool wim_noselect_next = (wim_flags[1] & kOptWimFlagNoselect); if (wim_list_next || (p_wmnu && (wim_full_next || wim_noselect_next))) { - if (wim_noselect_next) { - options |= WILD_NOSELECT; - } - if (wim_full_next || wim_noselect_next) { + if (wim_full_next && !wim_noselect_next) { nextwild(&s->xpc, WILD_NEXT, options, escape); + } else { + showmatches(&s->xpc, p_wmnu, wim_list_next, wim_noselect_next); } - showmatches(&s->xpc, p_wmnu, wim_list_next, wim_noselect_next); if (wim_list_next) { s->did_wild_list = true; } diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua @@ -4795,9 +4795,10 @@ describe('builtin popupmenu', function() :cn^ | ]]) - feed('<C-U><Esc>') command('set wildmode& wildoptions=pum') + feed('<C-U><Esc>') + -- check positioning with multibyte char in pattern command('e långfile1') command('sp långfile2') @@ -4981,24 +4982,52 @@ describe('builtin popupmenu', function() -- pressing <Tab> should display the wildmenu feed('<Tab>') - screen:expect([[ + local s1 = [[ | {1:~ }|*4 {1:~ }{12: undefine }{1: }| {1:~ }{n: unplace }{1: }| :sign undefine^ | - ]]) + ]] + screen:expect(s1) eq(1, fn.wildmenumode()) -- pressing <Tab> second time should select the next entry in the menu feed('<Tab>') - screen:expect([[ + local s2 = [[ | {1:~ }|*4 {1:~ }{n: undefine }{1: }| {1:~ }{12: unplace }{1: }| :sign unplace^ | + ]] + screen:expect(s2) + eq(1, fn.wildmenumode()) + + -- If "longest" finds no candidate in "longest,full", "full" is used + feed('<Esc>') + command('set wildmode=longest,full') + command('set wildoptions=pum') + feed(':sign un<Tab>') + screen:expect(s1) + feed('<Tab>') + screen:expect(s2) + + -- Similarly for "longest,noselect:full" + feed('<Esc>') + command('set wildmode=longest,noselect:full') + feed(':sign un<Tab>') + screen:expect([[ + | + {1:~ }|*4 + {1:~ }{n: undefine }{1: }| + {1:~ }{n: unplace }{1: }| + :sign un^ | ]]) + feed('<Tab>') + screen:expect(s1) + feed('<Tab>') + screen:expect(s2) end) it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function() diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim @@ -3044,6 +3044,23 @@ func Test_wildmenu_pum() call term_sendkeys(buf, ":cn\<Tab>") call VerifyScreenDump(buf, 'Test_wildmenu_pum_64', {}) + " If "longest" finds no candidate in "longest,full", "full" is used + call term_sendkeys(buf, "\<Esc>:set wildmode=longest,full\<CR>") + call term_sendkeys(buf, ":set wildoptions=pum\<CR>") + call term_sendkeys(buf, ":sign un\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_09', {}) + call term_sendkeys(buf, "\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_10', {}) + + " Similarly for "longest,noselect:full" + call term_sendkeys(buf, "\<Esc>:set wildmode=longest,noselect:full\<CR>") + call term_sendkeys(buf, ":sign un\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_65', {}) + call term_sendkeys(buf, "\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_09', {}) + call term_sendkeys(buf, "\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_10', {}) + call term_sendkeys(buf, "\<C-U>\<Esc>") call StopVimInTerminal(buf) endfunc