-*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
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
-*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
- 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 ~
-----------------
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;
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);
* 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;
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)
{
&& 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;
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;
&& !*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;
}
{
if (wim_noselect || wim_list)
options |= WILD_NOSELECT;
+ if (wim_noinsert)
+ options |= WILD_NOINSERT;
res = nextwild(xp, WILD_EXPAND_KEEP, options, escape);
}
}
// 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;
}
}
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);
}
{
// 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)
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
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;
#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.
#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};
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);
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
\ ['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']],
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 417,
/**/
416,
/**/
#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