c = safe_vgetc();
} while (c == K_IGNORE || c == K_NOP);
+ // If the cmdline was replaced externally (e.g. by setcmdline()
+ // during an <expr> mapping), clean up the wildmenu completion
+ // state to avoid using stale completion data.
+ if (ccline.cmdbuff_replaced && xpc.xp_numfiles > 0)
+ {
+ if (cmdline_pum_active())
+ cmdline_pum_remove(&ccline, FALSE);
+ (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
+ did_wild_list = FALSE;
+ xpc.xp_context = EXPAND_NOTHING;
+ wim_index = 0;
+ wildmenu_cleanup(&ccline);
+ }
+ ccline.cmdbuff_replaced = FALSE;
+
// Skip wildmenu during history navigation via Up/Down keys
if (c == K_WILD && did_hist_navigate)
{
p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
new_cmdpos = p->cmdpos;
+ p->cmdbuff_replaced = TRUE;
redrawcmd();
char_u *xp_arg; // user-defined expansion arg
int input_fn; // when TRUE Invoked for input() function
#endif
+ int cmdbuff_replaced; // when TRUE cmdline was replaced externally
+ // (e.g. by setcmdline())
} cmdline_info_T;
/*
call feedkeys(":a\<CR>", 'tx')
call assert_equal('let foo=0', @:)
cunmap a
+
+ " setcmdline() during wildmenu completion should not freeze.
+ " Stripping completion state when cmdline was replaced externally.
+ set wildmenu
+ call mkdir('Xsetcmdlinedir', 'pR')
+ call writefile([], 'Xsetcmdlinedir/Xfile1')
+ call writefile([], 'Xsetcmdlinedir/Xfile2')
+ func g:SetCmdLineEmpty()
+ call setcmdline('', 1)
+ return "\<Left>"
+ endfunc
+ cnoremap <expr> a g:SetCmdLineEmpty()
+ call feedkeys(":e Xsetcmdlinedir/\<Tab>a\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"', @:)
+ cunmap a
+ delfunc g:SetCmdLineEmpty
+ set nowildmenu
endfunc
func Test_rulerformat_position()
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 209,
/**/
208,
/**/