commit 7f2298ad32a6f1158f05b4f0a0c119bc65bfa554
parent acb99b8a6572d8ea8d917955a653945550923be0
Author: zeertzjq <zeertzjq@outlook.com>
Date: Tue, 9 Sep 2025 08:11:13 +0800
fix(cmdline): fix inconsistent behavior with ext_popupmenu (#35688)
Diffstat:
3 files changed, 108 insertions(+), 15 deletions(-)
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
@@ -451,6 +451,16 @@ bool cmdline_compl_is_fuzzy(void)
return xp != NULL && cmdline_fuzzy_completion_supported(xp);
}
+/// Checks whether popup menu should be used for cmdline completion wildmenu.
+///
+/// @param wildmenu whether wildmenu is needed by current 'wildmode' part
+bool cmdline_compl_use_pum(bool need_wildmenu)
+{
+ return ((need_wildmenu && (wop_flags & kOptWopFlagPum)
+ && !(ui_has(kUICmdline) && cmdline_win == NULL))
+ || ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu)));
+}
+
/// Return the number of characters that should be skipped in the wildmenu
/// These are backslashes used for escaping. Do show backslashes in help tags
/// and in search pattern completion matches.
@@ -748,7 +758,7 @@ static char *get_next_or_prev_match(int mode, expand_T *xp)
if (compl_match_array) {
compl_selected = findex;
cmdline_pum_display(false);
- } else if (wop_flags & kOptWopFlagPum) {
+ } else if (cmdline_compl_use_pum(true)) {
if (cmdline_pum_create(get_cmdline_info(), xp, xp->xp_files,
xp->xp_numfiles, cmd_showtail, false) == EXPAND_OK) {
compl_selected = findex;
@@ -1122,9 +1132,7 @@ int showmatches(expand_T *xp, bool display_wildmenu, bool display_list, bool nos
showtail = cmd_showtail;
}
- if (((!ui_has(kUICmdline) || cmdline_win != NULL) && display_wildmenu && !display_list
- && (wop_flags & kOptWopFlagPum))
- || ui_has(kUIWildmenu) || (ui_has(kUICmdline) && ui_has(kUIPopupmenu))) {
+ if (cmdline_compl_use_pum(display_wildmenu && !display_list)) {
int retval = cmdline_pum_create(ccline, xp, matches, numMatches, showtail, noselect);
if (retval == EXPAND_OK) {
compl_selected = noselect ? -1 : 0;
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
@@ -454,7 +454,7 @@ local function test_cmdline(linegrid)
}
end)
- it('works together with ext_popupmenu', function()
+ local function test_ext_cmdline_popupmenu()
local expected = {
{ 'define', '', '', '' },
{ 'jump', '', '', '' },
@@ -557,19 +557,63 @@ local function test_cmdline(linegrid)
{1:~ }|*3
|
]],
- cmdline = {
- {
- content = { { 'e wildpum/Xnamedir/XdirA/' } },
- firstc = ':',
- pos = 25,
- },
- },
+ cmdline = { { content = { { 'e wildpum/Xnamedir/XdirA/' } }, firstc = ':', pos = 25 } },
popupmenu = {
anchor = { -1, 0, 19 },
items = { { 'XdirA/', '', '', '' }, { 'XfileA', '', '', '' } },
pos = 0,
},
}
+
+ feed('<Esc>')
+ command('set wildmode=longest,full')
+ feed(':sign u<tab>')
+ screen:expect {
+ grid = [[
+ ^ |
+ {1:~ }|*3
+ |
+ ]],
+ cmdline = { { content = { { 'sign un' } }, firstc = ':', pos = 7 } },
+ }
+
+ feed('<tab>')
+ local s_undefine_unplace_0 = {
+ grid = [[
+ ^ |
+ {1:~ }|*3
+ |
+ ]],
+ cmdline = { { content = { { 'sign undefine' } }, firstc = ':', pos = 13 } },
+ popupmenu = {
+ anchor = { -1, 0, 5 },
+ items = { { 'undefine', '', '', '' }, { 'unplace', '', '', '' } },
+ pos = 0,
+ },
+ }
+ screen:expect(s_undefine_unplace_0)
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|*3
+ |
+ ]])
+
+ feed(':sign un<tab>')
+ screen:expect(s_undefine_unplace_0)
+ end
+
+ describe('works together with ext_popupmenu', function()
+ it('with wildoptions=pum', function()
+ command('set wildoptions=pum')
+ test_ext_cmdline_popupmenu()
+ end)
+
+ it('with wildoptions=', function()
+ command('set wildoptions=')
+ test_ext_cmdline_popupmenu()
+ end)
end)
it('ext_wildmenu takes precedence over ext_popupmenu', function()
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
@@ -593,7 +593,7 @@ describe('ui/ext_wildmenu', function()
screen = Screen.new(25, 5, { rgb = true, ext_wildmenu = true })
end)
- it('works with :sign <tab>', function()
+ local function test_ext_wildmenu_sign_cmd()
local expected = {
'define',
'jump',
@@ -650,12 +650,53 @@ describe('ui/ext_wildmenu', function()
}
feed('a')
- screen:expect {
- grid = [[
+ screen:expect([[
|
{1:~ }|*3
:sign definea^ |
+ ]])
+
+ feed('<Esc>')
+ command('set wildmode=longest,full')
+ feed(':sign u<tab>')
+ screen:expect([[
+ |
+ {1:~ }|*3
+ :sign un^ |
+ ]])
+
+ feed('<tab>')
+ local s_undefine_unplace_0 = {
+ grid = [[
+ |
+ {1:~ }|*3
+ :sign undefine^ |
]],
+ wildmenu_items = { 'undefine', 'unplace' },
+ wildmenu_pos = 0,
}
+ screen:expect(s_undefine_unplace_0)
+
+ feed('<Esc>')
+ screen:expect([[
+ ^ |
+ {1:~ }|*3
+ |
+ ]])
+
+ feed(':sign un<tab>')
+ screen:expect(s_undefine_unplace_0)
+ end
+
+ describe('works with :sign <tab>', function()
+ it('with wildoptions=pum', function()
+ command('set wildoptions=pum')
+ test_ext_wildmenu_sign_cmd()
+ end)
+
+ it('with wildoptions=', function()
+ command('set wildoptions=')
+ test_ext_wildmenu_sign_cmd()
+ end)
end)
end)