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

c7f235bd43
This commit is contained in:
zeertzjq
2025-09-08 08:15:54 +08:00
parent d784ed7013
commit 18f24b85c3
3 changed files with 53 additions and 9 deletions

View File

@@ -1188,13 +1188,11 @@ static int command_line_wildchar_complete(CommandLineState *s)
bool wim_full_next = (wim_flags[1] & kOptWimFlagFull); bool wim_full_next = (wim_flags[1] & kOptWimFlagFull);
bool wim_noselect_next = (wim_flags[1] & kOptWimFlagNoselect); bool wim_noselect_next = (wim_flags[1] & kOptWimFlagNoselect);
if (wim_list_next || (p_wmnu && (wim_full_next || wim_noselect_next))) { if (wim_list_next || (p_wmnu && (wim_full_next || wim_noselect_next))) {
if (wim_noselect_next) { if (wim_full_next && !wim_noselect_next) {
options |= WILD_NOSELECT;
}
if (wim_full_next || wim_noselect_next) {
nextwild(&s->xpc, WILD_NEXT, options, escape); 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) { if (wim_list_next) {
s->did_wild_list = true; s->did_wild_list = true;
} }

View File

@@ -4795,9 +4795,10 @@ describe('builtin popupmenu', function()
:cn^ | :cn^ |
]]) ]])
feed('<C-U><Esc>')
command('set wildmode& wildoptions=pum') command('set wildmode& wildoptions=pum')
feed('<C-U><Esc>')
-- check positioning with multibyte char in pattern -- check positioning with multibyte char in pattern
command('e långfile1') command('e långfile1')
command('sp långfile2') command('sp långfile2')
@@ -4981,24 +4982,52 @@ describe('builtin popupmenu', function()
-- pressing <Tab> should display the wildmenu -- pressing <Tab> should display the wildmenu
feed('<Tab>') feed('<Tab>')
screen:expect([[ local s1 = [[
| |
{1:~ }|*4 {1:~ }|*4
{1:~ }{12: undefine }{1: }| {1:~ }{12: undefine }{1: }|
{1:~ }{n: unplace }{1: }| {1:~ }{n: unplace }{1: }|
:sign undefine^ | :sign undefine^ |
]]) ]]
screen:expect(s1)
eq(1, fn.wildmenumode()) eq(1, fn.wildmenumode())
-- pressing <Tab> second time should select the next entry in the menu -- pressing <Tab> second time should select the next entry in the menu
feed('<Tab>') feed('<Tab>')
screen:expect([[ local s2 = [[
| |
{1:~ }|*4 {1:~ }|*4
{1:~ }{n: undefine }{1: }| {1:~ }{n: undefine }{1: }|
{1:~ }{12: unplace }{1: }| {1:~ }{12: unplace }{1: }|
:sign unplace^ | :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) end)
it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function() it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function()

View File

@@ -3044,6 +3044,23 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, ":cn\<Tab>") call term_sendkeys(buf, ":cn\<Tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_64', {}) 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 term_sendkeys(buf, "\<C-U>\<Esc>")
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc