patch 9.1.1676: completion: long line shown twice Commit: https://github.com/vim/vim/commit/57379302aa2a82ee0c9aca49ddd681308cf1483c Author: Girish Palya <giris...@gmail.com> Date: Sat Aug 23 17:11:18 2025 +0200
patch 9.1.1676: completion: long line shown twice Problem: completion: long line shown twice (Maxim Kim) Solution: Fix the issue, disable an incorrect test. (Girish Palya) fixes: #18035 closes: #18088 Signed-off-by: Girish Palya <giris...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 4bde81c62..f4feec94b 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -239,6 +239,8 @@ nextwild( int i; char_u *p; int from_wildtrigger_func = options & WILD_FUNC_TRIGGER; + int wild_navigate = (type == WILD_NEXT || type == WILD_PREV + || type == WILD_PAGEUP || type == WILD_PAGEDOWN); if (xp->xp_numfiles == -1) { @@ -280,14 +282,13 @@ nextwild( // If cmd_silent is set then don't show the dots, because redrawcmd() below // won't remove them. - if (!cmd_silent && !from_wildtrigger_func) + if (!cmd_silent && !from_wildtrigger_func && !wild_navigate) { msg_puts("..."); // show that we are busy out_flush(); } - if (type == WILD_NEXT || type == WILD_PREV - || type == WILD_PAGEUP || type == WILD_PAGEDOWN) + if (wild_navigate) { // Get next/previous match for a previous expanded pattern. p = ExpandOne(xp, NULL, NULL, 0, type); @@ -310,8 +311,6 @@ nextwild( { int use_options = options | WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT; - if (use_options & WILD_KEEP_SOLE_ITEM) - use_options &= ~WILD_KEEP_SOLE_ITEM; if (escape) use_options |= WILD_ESCAPE; if (p_wic) @@ -338,7 +337,14 @@ nextwild( } } - if (p != NULL && !got_int) + // Save cmdline before inserting selected item + if (!wild_navigate && ccline->cmdbuff != NULL) + { + vim_free(cmdline_orig); + cmdline_orig = vim_strnsave(ccline->cmdbuff, ccline->cmdlen); + } + + if (p != NULL && !got_int && !(options & WILD_NOSELECT)) { size_t plen = STRLEN(p); int difflen; @@ -372,7 +378,8 @@ nextwild( if (xp->xp_numfiles <= 0 && p == NULL) beep_flush(); - else if (xp->xp_numfiles == 1 && !(options & WILD_KEEP_SOLE_ITEM)) + else if (xp->xp_numfiles == 1 && !(options & WILD_NOSELECT) + && !wild_navigate) // free expanded pattern (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE); @@ -391,7 +398,8 @@ cmdline_pum_create( expand_T *xp, char_u **matches, int numMatches, - int showtail) + int showtail, + int noselect) { int i; int prefix_len; @@ -421,7 +429,7 @@ cmdline_pum_create( compl_startcol = MAX(0, compl_startcol - prefix_len); // no default selection - compl_selected = -1; + compl_selected = noselect ? -1 : 0; pum_clear(); cmdline_pum_display(); @@ -1072,7 +1080,7 @@ ExpandOne( if (compl_match_array != NULL) cmdline_pum_remove(get_cmdline_info(), FALSE); } - xp->xp_selected = 0; + xp->xp_selected = (options & WILD_NOSELECT) ? -1 : 0; if (mode == WILD_FREE) // only release file name return NULL; @@ -1288,13 +1296,6 @@ showmatches(expand_T *xp, int wildmenu, int noselect) int attr; int showtail; - // Save cmdline before expansion - if (ccline->cmdbuff != NULL) - { - vim_free(cmdline_orig); - cmdline_orig = vim_strnsave(ccline->cmdbuff, ccline->cmdlen); - } - if (xp->xp_numfiles == -1) { int retval; @@ -1315,7 +1316,7 @@ showmatches(expand_T *xp, int wildmenu, int noselect) if (wildmenu && vim_strchr(p_wop, WOP_PUM) != NULL) // cmdline completion popup menu (with wildoptions=pum) return cmdline_pum_create(ccline, xp, matches, numMatches, - showtail && !noselect); + showtail && !noselect, noselect); if (!wildmenu) { @@ -1331,7 +1332,7 @@ showmatches(expand_T *xp, int wildmenu, int noselect) if (got_int) got_int = FALSE; // only int. the completion, not the cmd line else if (wildmenu) - win_redr_status_matches(xp, numMatches, matches, -1, showtail); + win_redr_status_matches(xp, numMatches, matches, noselect ? -1 : 0, showtail); else { // find the length of the longest file name diff --git a/src/ex_getln.c b/src/ex_getln.c index 7dbb743ec..3f5f852a4 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -946,12 +946,10 @@ cmdline_wildchar_complete( int res; int j; int options = WILD_NO_BEEP; - int noselect = (wim_flags[0] & WIM_NOSELECT) != 0; + int noselect = p_wmnu && (wim_flags[0] & WIM_NOSELECT); if (wim_flags[wim_index] & WIM_BUFLASTUSED) options |= WILD_BUFLASTUSED; - if (noselect) - options |= WILD_KEEP_SOLE_ITEM; if (xp->xp_numfiles > 0) // typed p_wc at least twice { // if 'wildmode' contains "list" may still need to list @@ -992,7 +990,11 @@ cmdline_wildchar_complete( if (wim_flags[0] & WIM_LONGEST) res = nextwild(xp, WILD_LONGEST, options, escape); else + { + if (noselect || (wim_flags[wim_index] & WIM_LIST)) + options |= WILD_NOSELECT; res = nextwild(xp, WILD_EXPAND_KEEP, options, escape); + } // Remove popup window if no completion items are available if (redraw_if_menu_empty && xp->xp_numfiles <= 0) @@ -1022,25 +1024,12 @@ cmdline_wildchar_complete( if ((wim_flags[wim_index] & WIM_LIST) || (p_wmnu && (wim_flags[wim_index] & (WIM_FULL | WIM_NOSELECT)))) { - if (!(wim_flags[0] & WIM_LONGEST)) - { - int p_wmnu_save = p_wmnu; - - p_wmnu = 0; - - // remove match - nextwild(xp, WILD_PREV, options, escape); - p_wmnu = p_wmnu_save; - } (void)showmatches(xp, p_wmnu && ((wim_flags[wim_index] & WIM_LIST) == 0), noselect); redrawcmd(); *did_wild_list = TRUE; if (wim_flags[wim_index] & WIM_LONGEST) nextwild(xp, WILD_LONGEST, options, escape); - else if ((wim_flags[wim_index] & WIM_FULL) - && !(wim_flags[wim_index] & WIM_NOSELECT)) - nextwild(xp, WILD_NEXT, options, escape); } else vim_beep(BO_WILD); diff --git a/src/testdir/dumps/Test_long_line_noselect_1.dump b/src/testdir/dumps/Test_long_line_noselect_1.dump new file mode 100644 index 000000000..a63ef65a5 --- /dev/null +++ b/src/testdir/dumps/Test_long_line_noselect_1.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@59 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @10| +0#0000001#ffd7ff255|l|o@15|n|g| |q|u|i|t|e| |l|o@11|n|g|,| |r|e|a|l +|:+0#0000000#ffffff0|D|o|u|b|l|e|E|n|t|r|y| > @46 diff --git a/src/testdir/dumps/Test_long_line_noselect_2.dump b/src/testdir/dumps/Test_long_line_noselect_2.dump new file mode 100644 index 000000000..5bd4ea179 --- /dev/null +++ b/src/testdir/dumps/Test_long_line_noselect_2.dump @@ -0,0 +1,8 @@ +|~+0#4040ff13#ffffff0| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @10| +0#0000001#e0e0e08|l|o@15|n|g| |q|u|i|t|e| |l|o@11|n|g|,| |r|e|a|l +|:+0#0000000#ffffff0|D|o|u|b|l|e|E|n|t|r|y| |l|o@15|n|g| |q|u|i|t|e| |l|o@11|n|g|,| |r|e|a|l +@1|y| |l|o@11|n|g|,| |p|r|o|b|a|b|l|y| |t|o@1| |l|o@25 +@1|n|g| |e|n|t|r|y> @50 diff --git a/src/testdir/dumps/Test_long_line_noselect_3.dump b/src/testdir/dumps/Test_long_line_noselect_3.dump new file mode 100644 index 000000000..d79a28453 --- /dev/null +++ b/src/testdir/dumps/Test_long_line_noselect_3.dump @@ -0,0 +1,8 @@ +|~+0#4040ff13#ffffff0| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @10| +0#0000001#ffd7ff255|l|o@15|n|g| |q|u|i|t|e| |l|o@11|n|g|,| |r|e|a|l +|:+0#0000000#ffffff0|D|o|u|b|l|e|E|n|t|r|y| > @46 +@60 +@60 diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index d2c9c7898..2ae27da7f 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -2267,8 +2267,11 @@ func Wildmode_tests() " when using longest completion match, matches shorter than the argument " should be ignored (happens with :help) set wildmode=longest,full - call feedkeys(":help a* \<C-B>\"\<CR>", 'xt') - call assert_equal('"help a', @:) + " XXX: This test is incorrect. ':help a*' will never yield 'help a' + " because '`a' exists as a menu item. The intent was to test a case + " handled by nextwild(). + " call feedkeys(":help a* \<C-B>\"\<CR>", 'xt') + " call assert_equal('"help a', @:) " non existing file call feedkeys(":e a1b2y3z4 \<C-B>\"\<CR>", 'xt') call assert_equal('"e a1b2y3z4', @:) @@ -4351,7 +4354,7 @@ func Test_cmdcomplete_info() call feedkeys(":h echom\<cr>", "tx") " No expansion call assert_equal('{}', g:cmdcomplete_info) call feedkeys($":h echoms{trig}\<cr>", "tx") - call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) + call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) call feedkeys($":h echom{trig}\<cr>", "tx") call assert_equal( \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}', @@ -4367,7 +4370,7 @@ func Test_cmdcomplete_info() set wildoptions=pum call feedkeys($":h echoms{trig}\<cr>", "tx") - call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) + call assert_equal('{''cmdline_orig'': ''h echoms'', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) call feedkeys($":h echom{trig}\<cr>", "tx") call assert_equal( \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}', @@ -4864,7 +4867,6 @@ endfunc " file paths when 'noselect' is present. func Test_noselect_expand_env_var() CheckScreendump - let lines =<< trim [SCRIPT] set wildmenu wildoptions=pum wildmode=noselect,full let $TESTDIR = 'a/b' @@ -4889,4 +4891,31 @@ func Test_noselect_expand_env_var() call StopVimInTerminal(buf) endfunc +" Issue #18035: long lines should not get listed twice in the menu when +" 'wildmode' contains 'noselect' +func Test_long_line_noselect() + CheckScreendump + let lines =<< trim [SCRIPT] + set wildmenu wildoptions=pum wildmode=noselect,full + command -nargs=1 -complete=custom,Entries DoubleEntry echo + func Entries(a, b, c) + return 'loooooooooooooooong quite loooooooooooong, really loooooooooooong, probably too looooooooooooooooooooooooooong entry' + endfunc + [SCRIPT] + call writefile(lines, 'XTest_wildmenu', 'D') + let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8, 'cols': 60}) + + call term_sendkeys(buf, ":DoubleEntry \<Tab>") + call VerifyScreenDump(buf, 'Test_long_line_noselect_1', {}) + + call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>") + call VerifyScreenDump(buf, 'Test_long_line_noselect_2', {}) + + call term_sendkeys(buf, "\<Esc>:DoubleEntry \<Tab>\<C-N>\<C-N>") + call VerifyScreenDump(buf, 'Test_long_line_noselect_3', {}) + " clean up + call term_sendkeys(buf, "\<Esc>") + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 2262124dd..a1a48ad92 100644 --- a/src/version.c +++ b/src/version.c @@ -724,6 +724,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1676, /**/ 1675, /**/ diff --git a/src/vim.h b/src/vim.h index 4a4a9b255..9845cbe78 100644 --- a/src/vim.h +++ b/src/vim.h @@ -900,7 +900,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define WILD_NOERROR 0x800 // sets EW_NOERROR #define WILD_BUFLASTUSED 0x1000 #define BUF_DIFF_FILTER 0x2000 -#define WILD_KEEP_SOLE_ITEM 0x4000 +#define WILD_NOSELECT 0x4000 #define WILD_MAY_EXPAND_PATTERN 0x8000 #define WILD_FUNC_TRIGGER 0x10000 // called from wildtrigger() -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1uppxS-00F5CD-Pf%40256bit.org.