diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-08-24 10:28:32 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-24 10:28:32 +0800 |
commit | 9a100ee169f80cbfe45872939ed9b4f70f6bfe3f (patch) | |
tree | d9a3580d0934d46dd594e05d091e09fd4e0cbc4f | |
parent | 64d147b4719310093ca2d728ba68b23f7e0660df (diff) | |
download | rneovim-9a100ee169f80cbfe45872939ed9b4f70f6bfe3f.tar.gz rneovim-9a100ee169f80cbfe45872939ed9b4f70f6bfe3f.tar.bz2 rneovim-9a100ee169f80cbfe45872939ed9b4f70f6bfe3f.zip |
fix(cmdline): do not trigger completion at wrong time (#19920)
Cherry-picked from Vim patches 8.2.4339, 9.0.0238.
-rw-r--r-- | src/nvim/ex_getln.c | 18 | ||||
-rw-r--r-- | test/functional/ui/popupmenu_spec.lua | 16 | ||||
-rw-r--r-- | test/functional/ui/wildmode_spec.lua | 58 |
3 files changed, 82 insertions, 10 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0dce2fd2e2..febfff41e1 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1277,8 +1277,11 @@ static int command_line_execute(VimState *state, int key) // <S-Tab> goes to last match, in a clumsy way if (s->c == K_S_TAB && KeyTyped) { if (nextwild(&s->xpc, WILD_EXPAND_KEEP, 0, s->firstc != '@') == OK) { - // Trigger the popup menu when wildoptions=pum - showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + if (s->xpc.xp_numfiles > 1 + && ((!s->did_wild_list && (wim_flags[s->wim_index] & WIM_LIST)) || p_wmnu)) { + // Trigger the popup menu when wildoptions=pum + showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); + } nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); nextwild(&s->xpc, WILD_PREV, 0, s->firstc != '@'); return command_line_changed(s); @@ -1798,13 +1801,16 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); case Ctrl_A: // all matches - if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) { - break; - } if (cmdline_pum_active()) { + // As Ctrl-A completes all the matches, close the popup + // menu (if present) cmdline_pum_cleanup(&ccline); - s->xpc.xp_context = EXPAND_NOTHING; } + if (nextwild(&s->xpc, WILD_ALL, 0, s->firstc != '@') == FAIL) { + break; + } + s->xpc.xp_context = EXPAND_NOTHING; + s->did_wild_list = false; return command_line_changed(s); case Ctrl_L: diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index e11cd1e859..dcd4ad3d9a 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -1990,6 +1990,22 @@ describe('builtin popupmenu', function() efine unplace^ | ]]) + -- Pressing <Left> after that should move the cursor + feed('<Left>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {4: }| + :sign define jump list place und| + efine unplac^e | + ]]) + feed('<End>') + -- Pressing <C-D> when the popup menu is displayed should remove the popup -- menu feed('<C-U>sign <Tab><C-D>') diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 98398bc7a1..58ffa3bda8 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -461,20 +461,20 @@ end) describe('command line completion', function() local screen before_each(function() + clear() screen = Screen.new(40, 5) screen:set_default_attr_ids({ [1] = {bold = true, foreground = Screen.colors.Blue1}, [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow}, [3] = {bold = true, reverse = true}, }) + screen:attach() end) after_each(function() os.remove('Xtest-functional-viml-compl-dir') end) it('lists directories with empty PATH', function() - clear() - screen:attach() local tmp = funcs.tempname() command('e '.. tmp) command('cd %:h') @@ -491,8 +491,6 @@ describe('command line completion', function() end) it('completes env var names #9681', function() - clear() - screen:attach() command('let $XTEST_1 = "foo" | let $XTEST_2 = "bar"') command('set wildmenu wildmode=full') feed(':!echo $XTEST_<tab>') @@ -521,6 +519,58 @@ describe('command line completion', function() :!echo $XTEST_1AaあB^ | ]]) end) + + it('does not leak memory with <S-Tab> with wildmenu and only one match #19874', function() + meths.set_option('wildmenu', true) + meths.set_option('wildmode', 'full') + meths.set_option('wildoptions', 'pum') + + feed(':sign unpla<S-Tab>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + :sign unplace^ | + ]]) + + feed('<Space>buff<Tab>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + :sign unplace buffer=^ | + ]]) + end) + + it('does not show matches with <S-Tab> without wildmenu with wildmode=full', function() + meths.set_option('wildmenu', false) + meths.set_option('wildmode', 'full') + + feed(':sign <S-Tab>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + :sign unplace^ | + ]]) + end) + + it('shows matches with <S-Tab> without wildmenu with wildmode=list', function() + meths.set_option('wildmenu', false) + meths.set_option('wildmode', 'list') + + feed(':sign <S-Tab>') + screen:expect([[ + {3: }| + :sign define | + define list undefine | + jump place unplace | + :sign unplace^ | + ]]) + end) end) describe('ui/ext_wildmenu', function() |