Skip to content

Commit 0926389

Browse files
zeertzjqsmjonas
authored andcommitted
fix(cmdline): do not trigger completion at wrong time (neovim#19920)
Cherry-picked from Vim patches 8.2.4339, 9.0.0238.
1 parent ebd89c9 commit 0926389

File tree

3 files changed

+82
-10
lines changed

3 files changed

+82
-10
lines changed

src/nvim/ex_getln.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,8 +1277,11 @@ static int command_line_execute(VimState *state, int key)
12771277
// <S-Tab> goes to last match, in a clumsy way
12781278
if (s->c == K_S_TAB && KeyTyped) {
12791279
if (nextwild(&s->xpc, WILD_EXPAND_KEEP, 0, s->firstc != '@') == OK) {
1280-
// Trigger the popup menu when wildoptions=pum
1281-
showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
1280+
if (s->xpc.xp_numfiles > 1
1281+
&& ((!s->did_wild_list && (wim_flags[s->wim_index] & WIM_LIST)) || p_wmnu)) {
1282+
// Trigger the popup menu when wildoptions=pum
1283+
showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
1284+
}
12821285
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
12831286
nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@');
12841287
return command_line_changed(s);
@@ -1798,13 +1801,16 @@ static int command_line_handle_key(CommandLineState *s)
17981801
return command_line_not_changed(s);
17991802

18001803
case Ctrl_A: // all matches
1801-
if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) {
1802-
break;
1803-
}
18041804
if (cmdline_pum_active()) {
1805+
// As Ctrl-A completes all the matches, close the popup
1806+
// menu (if present)
18051807
cmdline_pum_cleanup(&ccline);
1806-
s->xpc.xp_context = EXPAND_NOTHING;
18071808
}
1809+
if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) {
1810+
break;
1811+
}
1812+
s->xpc.xp_context = EXPAND_NOTHING;
1813+
s->did_wild_list = false;
18081814
return command_line_changed(s);
18091815

18101816
case Ctrl_L:

test/functional/ui/popupmenu_spec.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,6 +1990,22 @@ describe('builtin popupmenu', function()
19901990
efine unplace^ |
19911991
]])
19921992

1993+
-- Pressing <Left> after that should move the cursor
1994+
feed('<Left>')
1995+
screen:expect([[
1996+
|
1997+
{1:~ }|
1998+
{1:~ }|
1999+
{1:~ }|
2000+
{1:~ }|
2001+
{1:~ }|
2002+
{1:~ }|
2003+
{4: }|
2004+
:sign define jump list place und|
2005+
efine unplac^e |
2006+
]])
2007+
feed('<End>')
2008+
19932009
-- Pressing <C-D> when the popup menu is displayed should remove the popup
19942010
-- menu
19952011
feed('<C-U>sign <Tab><C-D>')

test/functional/ui/wildmode_spec.lua

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,20 +461,20 @@ end)
461461
describe('command line completion', function()
462462
local screen
463463
before_each(function()
464+
clear()
464465
screen = Screen.new(40, 5)
465466
screen:set_default_attr_ids({
466467
[1] = {bold = true, foreground = Screen.colors.Blue1},
467468
[2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
468469
[3] = {bold = true, reverse = true},
469470
})
471+
screen:attach()
470472
end)
471473
after_each(function()
472474
os.remove('Xtest-functional-viml-compl-dir')
473475
end)
474476

475477
it('lists directories with empty PATH', function()
476-
clear()
477-
screen:attach()
478478
local tmp = funcs.tempname()
479479
command('e '.. tmp)
480480
command('cd %:h')
@@ -491,8 +491,6 @@ describe('command line completion', function()
491491
end)
492492

493493
it('completes env var names #9681', function()
494-
clear()
495-
screen:attach()
496494
command('let $XTEST_1 = "foo" | let $XTEST_2 = "bar"')
497495
command('set wildmenu wildmode=full')
498496
feed(':!echo $XTEST_<tab>')
@@ -521,6 +519,58 @@ describe('command line completion', function()
521519
:!echo $XTEST_1AaあB^ |
522520
]])
523521
end)
522+
523+
it('does not leak memory with <S-Tab> with wildmenu and only one match #19874', function()
524+
meths.set_option('wildmenu', true)
525+
meths.set_option('wildmode', 'full')
526+
meths.set_option('wildoptions', 'pum')
527+
528+
feed(':sign unpla<S-Tab>')
529+
screen:expect([[
530+
|
531+
{1:~ }|
532+
{1:~ }|
533+
{1:~ }|
534+
:sign unplace^ |
535+
]])
536+
537+
feed('<Space>buff<Tab>')
538+
screen:expect([[
539+
|
540+
{1:~ }|
541+
{1:~ }|
542+
{1:~ }|
543+
:sign unplace buffer=^ |
544+
]])
545+
end)
546+
547+
it('does not show matches with <S-Tab> without wildmenu with wildmode=full', function()
548+
meths.set_option('wildmenu', false)
549+
meths.set_option('wildmode', 'full')
550+
551+
feed(':sign <S-Tab>')
552+
screen:expect([[
553+
|
554+
{1:~ }|
555+
{1:~ }|
556+
{1:~ }|
557+
:sign unplace^ |
558+
]])
559+
end)
560+
561+
it('shows matches with <S-Tab> without wildmenu with wildmode=list', function()
562+
meths.set_option('wildmenu', false)
563+
meths.set_option('wildmode', 'list')
564+
565+
feed(':sign <S-Tab>')
566+
screen:expect([[
567+
{3: }|
568+
:sign define |
569+
define list undefine |
570+
jump place unplace |
571+
:sign unplace^ |
572+
]])
573+
end)
524574
end)
525575

526576
describe('ui/ext_wildmenu', function()

0 commit comments

Comments
 (0)