mirror of
https://github.com/vim/vim.git
synced 2026-05-06 12:26:58 -04:00
patch 9.2.0417: completion: no support for "noinsert" with 'wildmode'
Problem: completion: no support for "noinsert" with 'wildmode' and
commandline completion
Solution: Add "noinsert" value to the 'wildmode' option, mirroring
'completeopt' "noinsert" behaviour (glepnir).
fixes: #16551
closes: #20080
Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
c2bda0add9
commit
af494af5ff
@@ -1,4 +1,4 @@
|
||||
*options.txt* For Vim version 9.2. Last change: 2026 Apr 28
|
||||
*options.txt* For Vim version 9.2. Last change: 2026 Apr 29
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -10398,8 +10398,12 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
applies to buffer name completion.
|
||||
"noselect" If 'wildmenu' is enabled, show the menu but do not
|
||||
preselect the first item.
|
||||
If only one match exists, it is completed fully, unless "noselect" is
|
||||
specified.
|
||||
"noinsert" If 'wildmenu' is enabled, show the menu and preselect
|
||||
the first match, but do not insert it in the
|
||||
command line. If both "noinsert" and "noselect" are
|
||||
present, "noselect" takes precedence.
|
||||
If only one match exists, it is completed fully, unless "noselect" or
|
||||
"noinsert" is specified.
|
||||
|
||||
Some useful combinations of colon-separated values:
|
||||
"longest:full" Start with the longest common string and show
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*version9.txt* For Vim version 9.2. Last change: 2026 Apr 28
|
||||
*version9.txt* For Vim version 9.2. Last change: 2026 Apr 29
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -52618,6 +52618,8 @@ Other ~
|
||||
- Enable reflow support in the |:terminal|.
|
||||
- Enabled scrolling for the tabpanel when the tab page list exceeds the screen
|
||||
height. Also added the "scrollbar" sub-option to 'tabpanelopt'.
|
||||
- Added the "noinsert" value to the 'wildmode' option for symmetry with the
|
||||
'completeopt' option
|
||||
|
||||
Platform specific ~
|
||||
-----------------
|
||||
|
||||
+12
-4
@@ -346,7 +346,7 @@ nextwild(
|
||||
cmdline_orig.length = ccline->cmdlen;
|
||||
}
|
||||
|
||||
if (p != NULL && !got_int && !(options & WILD_NOSELECT))
|
||||
if (p != NULL && !got_int && !(options & (WILD_NOSELECT | WILD_NOINSERT)))
|
||||
{
|
||||
size_t plen = STRLEN(p);
|
||||
int difflen;
|
||||
@@ -380,7 +380,8 @@ nextwild(
|
||||
|
||||
if (xp->xp_numfiles <= 0 && p == NULL)
|
||||
beep_flush();
|
||||
else if (xp->xp_numfiles == 1 && !(options & WILD_NOSELECT)
|
||||
else if (xp->xp_numfiles == 1
|
||||
&& !(options & (WILD_NOSELECT | WILD_NOINSERT))
|
||||
&& !wild_navigate)
|
||||
// free expanded pattern
|
||||
(void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
|
||||
@@ -1295,7 +1296,11 @@ showmatches_oneline(
|
||||
* inserted as a normal character.
|
||||
*/
|
||||
int
|
||||
showmatches(expand_T *xp, int display_wildmenu, int display_list, int noselect)
|
||||
showmatches(
|
||||
expand_T *xp,
|
||||
int display_wildmenu,
|
||||
int display_list,
|
||||
int wim_flags_arg)
|
||||
{
|
||||
cmdline_info_T *ccline = get_cmdline_info();
|
||||
int numMatches;
|
||||
@@ -1306,6 +1311,9 @@ showmatches(expand_T *xp, int display_wildmenu, int display_list, int noselect)
|
||||
int columns;
|
||||
int attr;
|
||||
int showtail;
|
||||
int noselect = (wim_flags_arg & WIM_NOSELECT);
|
||||
int noinsert = (wim_flags_arg & WIM_NOINSERT);
|
||||
int cmdline_unchanged = noselect || noinsert;
|
||||
|
||||
if (xp->xp_numfiles == -1)
|
||||
{
|
||||
@@ -1328,7 +1336,7 @@ showmatches(expand_T *xp, int display_wildmenu, int display_list, int noselect)
|
||||
&& vim_strchr(p_wop, WOP_PUM) != NULL)
|
||||
{
|
||||
int retval = cmdline_pum_create(ccline, xp, matches, numMatches,
|
||||
showtail && !noselect);
|
||||
showtail && !cmdline_unchanged);
|
||||
if (retval == EXPAND_OK)
|
||||
{
|
||||
compl_selected = noselect ? -1 : 0;
|
||||
|
||||
+20
-10
@@ -958,6 +958,7 @@ cmdline_wildchar_complete(
|
||||
int cmdpos_before;
|
||||
int options = WILD_NO_BEEP;
|
||||
int wim_noselect = p_wmnu && (wim_flags[0] & WIM_NOSELECT);
|
||||
int wim_noinsert = p_wmnu && (wim_flags[0] & WIM_NOINSERT);
|
||||
|
||||
if (wim_flags[wim_index] & WIM_BUFLASTUSED)
|
||||
options |= WILD_BUFLASTUSED;
|
||||
@@ -968,7 +969,8 @@ cmdline_wildchar_complete(
|
||||
&& !*did_wild_list
|
||||
&& (wim_flags[wim_index] & WIM_LIST))
|
||||
{
|
||||
(void)showmatches(xp, FALSE, TRUE, wim_noselect);
|
||||
(void)showmatches(xp, FALSE, TRUE,
|
||||
p_wmnu ? wim_flags[wim_index] : 0);
|
||||
redrawcmd();
|
||||
*did_wild_list = TRUE;
|
||||
}
|
||||
@@ -1006,6 +1008,8 @@ cmdline_wildchar_complete(
|
||||
{
|
||||
if (wim_noselect || wim_list)
|
||||
options |= WILD_NOSELECT;
|
||||
if (wim_noinsert)
|
||||
options |= WILD_NOINSERT;
|
||||
res = nextwild(xp, WILD_EXPAND_KEEP, options, escape);
|
||||
}
|
||||
|
||||
@@ -1028,26 +1032,28 @@ cmdline_wildchar_complete(
|
||||
}
|
||||
|
||||
// Display matches
|
||||
if (res == OK && xp->xp_numfiles > (wim_noselect ? 0 : 1))
|
||||
if (res == OK && xp->xp_numfiles > ((wim_noselect || wim_noinsert) ? 0 : 1))
|
||||
{
|
||||
if (wim_longest)
|
||||
{
|
||||
int found_longest_prefix = (ccline.cmdpos != cmdpos_before);
|
||||
if (wim_list || (p_wmnu && wim_full))
|
||||
(void)showmatches(xp, p_wmnu, wim_list, TRUE);
|
||||
(void)showmatches(xp, p_wmnu, wim_list, WIM_NOSELECT);
|
||||
else if (!found_longest_prefix)
|
||||
{
|
||||
int wim_list_next = (wim_flags[1] & WIM_LIST);
|
||||
int wim_full_next = (wim_flags[1] & WIM_FULL);
|
||||
int wim_noselect_next = (wim_flags[1] & WIM_NOSELECT);
|
||||
int wim_noinsert_next = (wim_flags[1] & WIM_NOINSERT);
|
||||
if (wim_list_next || (p_wmnu && (wim_full_next
|
||||
|| wim_noselect_next)))
|
||||
|| wim_noselect_next || wim_noinsert_next)))
|
||||
{
|
||||
if (wim_full_next && !wim_noselect_next)
|
||||
if (wim_full_next && !wim_noselect_next && !wim_noinsert_next)
|
||||
nextwild(xp, WILD_NEXT, options, escape);
|
||||
else
|
||||
(void)showmatches(xp, p_wmnu, wim_list_next,
|
||||
wim_noselect_next);
|
||||
p_wmnu ? wim_flags[1] : 0);
|
||||
|
||||
if (wim_list_next)
|
||||
*did_wild_list = TRUE;
|
||||
}
|
||||
@@ -1055,8 +1061,10 @@ cmdline_wildchar_complete(
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wim_list || (p_wmnu && (wim_full || wim_noselect)))
|
||||
(void)showmatches(xp, p_wmnu, wim_list, wim_noselect);
|
||||
if (wim_list || (p_wmnu && (wim_full || wim_noselect
|
||||
|| wim_noinsert)))
|
||||
(void)showmatches(xp, p_wmnu, wim_list,
|
||||
p_wmnu ? wim_flags[0] : 0);
|
||||
else
|
||||
vim_beep(BO_WILD);
|
||||
}
|
||||
@@ -2181,7 +2189,7 @@ getcmdline_int(
|
||||
{
|
||||
// Trigger the popup menu when wildoptions=pum
|
||||
showmatches(&xpc, p_wmnu, wim_flags[wim_index] & WIM_LIST,
|
||||
wim_flags[0] & WIM_NOSELECT);
|
||||
p_wmnu ? wim_flags[0] : 0);
|
||||
}
|
||||
if (nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK
|
||||
&& nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK)
|
||||
@@ -2296,7 +2304,7 @@ getcmdline_int(
|
||||
goto cmdline_not_changed;
|
||||
|
||||
case Ctrl_D:
|
||||
if (showmatches(&xpc, FALSE, TRUE, wim_flags[0] & WIM_NOSELECT)
|
||||
if (showmatches(&xpc, FALSE, TRUE, p_wmnu ? wim_flags[0] : 0)
|
||||
== EXPAND_NOTHING)
|
||||
break; // Use ^D as normal char instead
|
||||
|
||||
@@ -2900,6 +2908,8 @@ check_opt_wim(void)
|
||||
new_wim_flags[idx] |= WIM_BUFLASTUSED;
|
||||
else if (i == 8 && STRNCMP(p, "noselect", 8) == 0)
|
||||
new_wim_flags[idx] |= WIM_NOSELECT;
|
||||
else if (i == 8 && STRNCMP(p, "noinsert", 8) == 0)
|
||||
new_wim_flags[idx] |= WIM_NOINSERT;
|
||||
else
|
||||
return FAIL;
|
||||
p += i;
|
||||
|
||||
@@ -375,6 +375,7 @@ typedef enum {
|
||||
#define WIM_LIST 0x04
|
||||
#define WIM_BUFLASTUSED 0x08
|
||||
#define WIM_NOSELECT 0x10
|
||||
#define WIM_NOINSERT 0x20
|
||||
|
||||
// flags for the 'wildoptions' option
|
||||
// each defined char should be unique over all values.
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm"
|
||||
#endif
|
||||
static char *(p_ve_values[]) = {"block", "insert", "all", "onemore", "none", "NONE", NULL};
|
||||
// Note: Keep this in sync with check_opt_wim()
|
||||
static char *(p_wim_values[]) = {"full", "longest", "list", "lastused", "noselect", NULL};
|
||||
static char *(p_wim_values[]) = {"full", "longest", "list", "lastused", "noselect", "noinsert", NULL};
|
||||
static char *(p_wop_values[]) = {"fuzzy", "tagfile", "pum", "exacttext", NULL};
|
||||
#ifdef FEAT_WAK
|
||||
static char *(p_wak_values[]) = {"yes", "menu", "no", NULL};
|
||||
|
||||
@@ -12,7 +12,7 @@ char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode
|
||||
void ExpandInit(expand_T *xp);
|
||||
void ExpandCleanup(expand_T *xp);
|
||||
void clear_cmdline_orig(void);
|
||||
int showmatches(expand_T *xp, int display_wildmenu, int display_list, int noselect);
|
||||
int showmatches(expand_T *xp, int display_wildmenu, int display_list, int wim_flags_arg);
|
||||
char_u *addstar(char_u *fname, int len, int context);
|
||||
void set_expand_context(expand_T *xp);
|
||||
void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline);
|
||||
|
||||
@@ -5416,4 +5416,94 @@ func Test_cmdline_complete_with_space()
|
||||
call chdir(save_cwd)
|
||||
endfunc
|
||||
|
||||
func Test_wildmode_noinsert()
|
||||
command! -nargs=1 -complete=custom,T MyCmd echo
|
||||
func T(a, c, p)
|
||||
return "oneA\noneB\noneC"
|
||||
endfunc
|
||||
|
||||
set wildmenu wildoptions=pum wildmode=noinsert,full wildchar=<Tab>
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneB', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneC', @:)
|
||||
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-Y>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneA', @:)
|
||||
|
||||
" CTRL-P from highlighted first item returns to original text
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-P>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
" Another CTRL-P wraps to the last match
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-P>\<C-P>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneC', @:)
|
||||
|
||||
set wildoptions=
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneB', @:)
|
||||
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-Y>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneA', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-E>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
|
||||
" 'nowildmenu' should make 'noinsert' ineffective
|
||||
set nowildmenu
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneA', @:)
|
||||
|
||||
" 'noselect' takes precedence over 'noinsert'
|
||||
set wildmenu wildoptions=pum wildmode=noselect:noinsert,full
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneA', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-Y>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
|
||||
set wildmode=noinsert
|
||||
call feedkeys(":MyCmd o\<Tab>\<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
|
||||
set wildmode=noinsert,full
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-N>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd oneB', @:)
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-E>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd o', @:)
|
||||
|
||||
" 'longest' takes precedence over 'noinsert'
|
||||
set wildmode=noinsert:longest
|
||||
call feedkeys(":MyCmd o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd one', @:)
|
||||
|
||||
set wildmode&
|
||||
call feedkeys(":set wildmode=noi\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"set wildmode=noinsert', @:)
|
||||
|
||||
set wildmode=noinsert:lastused,full
|
||||
call assert_equal('noinsert:lastused,full', &wildmode)
|
||||
call assert_fails('set wildmode=noinser', 'E474:')
|
||||
|
||||
" Single match with 'noinsert': item shown highlighted, C-Y commits
|
||||
command! -nargs=1 -complete=custom,T1 MyCmd1 echo
|
||||
func T1(a, c, p)
|
||||
return "oneA"
|
||||
endfunc
|
||||
set wildmenu wildoptions=pum wildmode=noinsert,full
|
||||
call feedkeys(":MyCmd1 o\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd1 o', @:)
|
||||
call feedkeys(":MyCmd1 o\<Tab>\<C-Y>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd1 oneA', @:)
|
||||
delcommand MyCmd1
|
||||
delfunc T1
|
||||
|
||||
set wildmenu& wildoptions& wildmode& wildchar&
|
||||
delcommand MyCmd
|
||||
delfunc T
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -365,6 +365,7 @@ let test_values = {
|
||||
\ ['xxx']],
|
||||
\ 'wildmode': [['', 'full', 'longest', 'list', 'lastused', 'list:full',
|
||||
\ 'noselect', 'noselect,full', 'noselect:lastused,full',
|
||||
\ 'noinsert', 'noinsert,full', 'noinsert:lastused,full',
|
||||
\ 'full,longest', 'full,full,full,full'],
|
||||
\ ['xxx', 'a4', 'full,full,full,full,full']],
|
||||
\ 'wildoptions': [['', 'tagfile', 'pum', 'fuzzy'], ['xxx']],
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
417,
|
||||
/**/
|
||||
416,
|
||||
/**/
|
||||
|
||||
@@ -904,6 +904,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
||||
#define WILD_NOSELECT 0x4000
|
||||
#define WILD_MAY_EXPAND_PATTERN 0x8000
|
||||
#define WILD_FUNC_TRIGGER 0x10000 // called from wildtrigger()
|
||||
#define WILD_NOINSERT 0x20000
|
||||
|
||||
// Flags for expand_wildcards()
|
||||
#define EW_DIR 0x01 // include directory names
|
||||
|
||||
Reference in New Issue
Block a user