mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.1634: loop to handle keys for the command line is too long
Problem: Loop to handle keys for the command line is too long. Solution: Move a few more parts to separate functions. (Yegappan Lakshmanan, closes #6895)
This commit is contained in:
481
src/ex_getln.c
481
src/ex_getln.c
@@ -21,6 +21,7 @@
|
|||||||
#define CMDLINE_NOT_CHANGED 1
|
#define CMDLINE_NOT_CHANGED 1
|
||||||
#define CMDLINE_CHANGED 2
|
#define CMDLINE_CHANGED 2
|
||||||
#define GOTO_NORMAL_MODE 3
|
#define GOTO_NORMAL_MODE 3
|
||||||
|
#define PROCESS_NEXT_KEY 4
|
||||||
|
|
||||||
// The current cmdline_info. It is initialized in getcmdline() and after that
|
// The current cmdline_info. It is initialized in getcmdline() and after that
|
||||||
// used by other functions. When invoking getcmdline() recursively it needs
|
// used by other functions. When invoking getcmdline() recursively it needs
|
||||||
@@ -39,7 +40,7 @@ static int extra_char_shift;
|
|||||||
static int cmd_hkmap = 0; // Hebrew mapping during command line
|
static int cmd_hkmap = 0; // Hebrew mapping during command line
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char_u *getcmdline_int(int firstc, long count, int indent, int init_ccline);
|
static char_u *getcmdline_int(int firstc, long count, int indent, int clear_ccline);
|
||||||
static int cmdline_charsize(int idx);
|
static int cmdline_charsize(int idx);
|
||||||
static void set_cmdspos(void);
|
static void set_cmdspos(void);
|
||||||
static void set_cmdspos_cursor(void);
|
static void set_cmdspos_cursor(void);
|
||||||
@@ -767,6 +768,220 @@ cmdline_init(void)
|
|||||||
CLEAR_FIELD(ccline);
|
CLEAR_FIELD(ccline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the backslash key pressed in the command-line mode. CTRL-\ CTRL-N
|
||||||
|
* goes to Normal mode, CTRL-\ CTRL-G goes to Insert mode when 'insertmode' is
|
||||||
|
* set, CTRL-\ e prompts for an expression.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmdline_handle_backslash_key(int c, int *gotesc)
|
||||||
|
{
|
||||||
|
++no_mapping;
|
||||||
|
++allow_keys;
|
||||||
|
c = plain_vgetc();
|
||||||
|
--no_mapping;
|
||||||
|
--allow_keys;
|
||||||
|
|
||||||
|
// CTRL-\ e doesn't work when obtaining an expression, unless it
|
||||||
|
// is in a mapping.
|
||||||
|
if (c != Ctrl_N && c != Ctrl_G && (c != 'e'
|
||||||
|
|| (ccline.cmdfirstc == '=' && KeyTyped)
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
|| cmdline_star > 0
|
||||||
|
#endif
|
||||||
|
))
|
||||||
|
{
|
||||||
|
vungetc(c);
|
||||||
|
return PROCESS_NEXT_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (c == 'e')
|
||||||
|
{
|
||||||
|
char_u *p = NULL;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace the command line with the result of an expression.
|
||||||
|
* Need to save and restore the current command line, to be
|
||||||
|
* able to enter a new one...
|
||||||
|
*/
|
||||||
|
if (ccline.cmdpos == ccline.cmdlen)
|
||||||
|
new_cmdpos = 99999; // keep it at the end
|
||||||
|
else
|
||||||
|
new_cmdpos = ccline.cmdpos;
|
||||||
|
|
||||||
|
c = get_expr_register();
|
||||||
|
if (c == '=')
|
||||||
|
{
|
||||||
|
// Need to save and restore ccline. And set "textwinlock"
|
||||||
|
// to avoid nasty things like going to another buffer when
|
||||||
|
// evaluating an expression.
|
||||||
|
++textwinlock;
|
||||||
|
p = get_expr_line();
|
||||||
|
--textwinlock;
|
||||||
|
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
len = (int)STRLEN(p);
|
||||||
|
if (realloc_cmdbuff(len + 1) == OK)
|
||||||
|
{
|
||||||
|
ccline.cmdlen = len;
|
||||||
|
STRCPY(ccline.cmdbuff, p);
|
||||||
|
vim_free(p);
|
||||||
|
|
||||||
|
// Restore the cursor or use the position set with
|
||||||
|
// set_cmdline_pos().
|
||||||
|
if (new_cmdpos > ccline.cmdlen)
|
||||||
|
ccline.cmdpos = ccline.cmdlen;
|
||||||
|
else
|
||||||
|
ccline.cmdpos = new_cmdpos;
|
||||||
|
|
||||||
|
KeyTyped = FALSE; // Don't do p_wc completion.
|
||||||
|
redrawcmd();
|
||||||
|
return CMDLINE_CHANGED;
|
||||||
|
}
|
||||||
|
vim_free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
beep_flush();
|
||||||
|
got_int = FALSE; // don't abandon the command line
|
||||||
|
did_emsg = FALSE;
|
||||||
|
emsg_on_display = FALSE;
|
||||||
|
redrawcmd();
|
||||||
|
return CMDLINE_NOT_CHANGED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (c == Ctrl_G && p_im && restart_edit == 0)
|
||||||
|
restart_edit = 'a';
|
||||||
|
*gotesc = TRUE; // will free ccline.cmdbuff after putting it
|
||||||
|
// in history
|
||||||
|
return GOTO_NORMAL_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Completion for 'wildchar' or 'wildcharm' key.
|
||||||
|
* - hitting <ESC> twice means: abandon command line.
|
||||||
|
* - wildcard expansion is only done when the 'wildchar' key is really
|
||||||
|
* typed, not when it comes from a macro
|
||||||
|
* Returns CMDLINE_CHANGED if command line is changed or CMDLINE_NOT_CHANGED.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmdline_wildchar_complete(
|
||||||
|
int c,
|
||||||
|
int escape,
|
||||||
|
int *did_wild_list,
|
||||||
|
int *wim_index_p,
|
||||||
|
expand_T *xp,
|
||||||
|
int *gotesc)
|
||||||
|
{
|
||||||
|
int wim_index = *wim_index_p;
|
||||||
|
int res;
|
||||||
|
int j;
|
||||||
|
int options = WILD_NO_BEEP;
|
||||||
|
|
||||||
|
if (wim_flags[wim_index] & WIM_BUFLASTUSED)
|
||||||
|
options |= WILD_BUFLASTUSED;
|
||||||
|
if (xp->xp_numfiles > 0) // typed p_wc at least twice
|
||||||
|
{
|
||||||
|
// if 'wildmode' contains "list" may still need to list
|
||||||
|
if (xp->xp_numfiles > 1
|
||||||
|
&& !*did_wild_list
|
||||||
|
&& (wim_flags[wim_index] & WIM_LIST))
|
||||||
|
{
|
||||||
|
(void)showmatches(xp, FALSE);
|
||||||
|
redrawcmd();
|
||||||
|
*did_wild_list = TRUE;
|
||||||
|
}
|
||||||
|
if (wim_flags[wim_index] & WIM_LONGEST)
|
||||||
|
res = nextwild(xp, WILD_LONGEST, options, escape);
|
||||||
|
else if (wim_flags[wim_index] & WIM_FULL)
|
||||||
|
res = nextwild(xp, WILD_NEXT, options, escape);
|
||||||
|
else
|
||||||
|
res = OK; // don't insert 'wildchar' now
|
||||||
|
}
|
||||||
|
else // typed p_wc first time
|
||||||
|
{
|
||||||
|
wim_index = 0;
|
||||||
|
j = ccline.cmdpos;
|
||||||
|
// if 'wildmode' first contains "longest", get longest
|
||||||
|
// common part
|
||||||
|
if (wim_flags[0] & WIM_LONGEST)
|
||||||
|
res = nextwild(xp, WILD_LONGEST, options, escape);
|
||||||
|
else
|
||||||
|
res = nextwild(xp, WILD_EXPAND_KEEP, options, escape);
|
||||||
|
|
||||||
|
// if interrupted while completing, behave like it failed
|
||||||
|
if (got_int)
|
||||||
|
{
|
||||||
|
(void)vpeekc(); // remove <C-C> from input stream
|
||||||
|
got_int = FALSE; // don't abandon the command line
|
||||||
|
(void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
#endif
|
||||||
|
*wim_index_p = wim_index;
|
||||||
|
return CMDLINE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when more than one match, and 'wildmode' first contains
|
||||||
|
// "list", or no change and 'wildmode' contains "longest,list",
|
||||||
|
// list all matches
|
||||||
|
if (res == OK && xp->xp_numfiles > 1)
|
||||||
|
{
|
||||||
|
// a "longest" that didn't do anything is skipped (but not
|
||||||
|
// "list:longest")
|
||||||
|
if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j)
|
||||||
|
wim_index = 1;
|
||||||
|
if ((wim_flags[wim_index] & WIM_LIST)
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
|| (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!(wim_flags[0] & WIM_LONGEST))
|
||||||
|
{
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
int p_wmnu_save = p_wmnu;
|
||||||
|
p_wmnu = 0;
|
||||||
|
#endif
|
||||||
|
// remove match
|
||||||
|
nextwild(xp, WILD_PREV, 0, escape);
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
p_wmnu = p_wmnu_save;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
(void)showmatches(xp, p_wmnu
|
||||||
|
&& ((wim_flags[wim_index] & WIM_LIST) == 0));
|
||||||
|
#else
|
||||||
|
(void)showmatches(xp, FALSE);
|
||||||
|
#endif
|
||||||
|
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)
|
||||||
|
nextwild(xp, WILD_NEXT, options, escape);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vim_beep(BO_WILD);
|
||||||
|
}
|
||||||
|
#ifdef FEAT_WILDMENU
|
||||||
|
else if (xp->xp_numfiles == -1)
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (wim_index < 3)
|
||||||
|
++wim_index;
|
||||||
|
if (c == ESC)
|
||||||
|
*gotesc = TRUE;
|
||||||
|
|
||||||
|
*wim_index_p = wim_index;
|
||||||
|
return (res == OK) ? CMDLINE_CHANGED : CMDLINE_NOT_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle backspace, delete and CTRL-W keys in the command-line mode.
|
* Handle backspace, delete and CTRL-W keys in the command-line mode.
|
||||||
* Returns:
|
* Returns:
|
||||||
@@ -1244,6 +1459,41 @@ done:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the current command-line info.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
init_ccline(int firstc, int indent)
|
||||||
|
{
|
||||||
|
ccline.overstrike = FALSE; // always start in insert mode
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set some variables for redrawcmd()
|
||||||
|
*/
|
||||||
|
ccline.cmdfirstc = (firstc == '@' ? 0 : firstc);
|
||||||
|
ccline.cmdindent = (firstc > 0 ? indent : 0);
|
||||||
|
|
||||||
|
// alloc initial ccline.cmdbuff
|
||||||
|
alloc_cmdbuff(exmode_active ? 250 : indent + 1);
|
||||||
|
if (ccline.cmdbuff == NULL)
|
||||||
|
return FAIL;
|
||||||
|
ccline.cmdlen = ccline.cmdpos = 0;
|
||||||
|
ccline.cmdbuff[0] = NUL;
|
||||||
|
sb_text_start_cmdline();
|
||||||
|
|
||||||
|
// autoindent for :insert and :append
|
||||||
|
if (firstc <= 0)
|
||||||
|
{
|
||||||
|
vim_memset(ccline.cmdbuff, ' ', indent);
|
||||||
|
ccline.cmdbuff[indent] = NUL;
|
||||||
|
ccline.cmdpos = indent;
|
||||||
|
ccline.cmdspos = indent;
|
||||||
|
ccline.cmdlen = indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getcmdline() - accept a command line starting with firstc.
|
* getcmdline() - accept a command line starting with firstc.
|
||||||
*
|
*
|
||||||
@@ -1278,7 +1528,7 @@ getcmdline_int(
|
|||||||
int firstc,
|
int firstc,
|
||||||
long count UNUSED, // only used for incremental search
|
long count UNUSED, // only used for incremental search
|
||||||
int indent, // indent for inside conditionals
|
int indent, // indent for inside conditionals
|
||||||
int init_ccline) // clear ccline first
|
int clear_ccline) // clear ccline first
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int i;
|
int i;
|
||||||
@@ -1316,7 +1566,7 @@ getcmdline_int(
|
|||||||
save_cmdline(&save_ccline);
|
save_cmdline(&save_ccline);
|
||||||
did_save_ccline = TRUE;
|
did_save_ccline = TRUE;
|
||||||
}
|
}
|
||||||
if (init_ccline)
|
if (clear_ccline)
|
||||||
CLEAR_FIELD(ccline);
|
CLEAR_FIELD(ccline);
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
@@ -1332,35 +1582,12 @@ getcmdline_int(
|
|||||||
cmd_hkmap = 0;
|
cmd_hkmap = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ccline.overstrike = FALSE; // always start in insert mode
|
|
||||||
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
init_incsearch_state(&is_state);
|
init_incsearch_state(&is_state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
if (init_ccline(firstc, indent) != OK)
|
||||||
* set some variables for redrawcmd()
|
|
||||||
*/
|
|
||||||
ccline.cmdfirstc = (firstc == '@' ? 0 : firstc);
|
|
||||||
ccline.cmdindent = (firstc > 0 ? indent : 0);
|
|
||||||
|
|
||||||
// alloc initial ccline.cmdbuff
|
|
||||||
alloc_cmdbuff(exmode_active ? 250 : indent + 1);
|
|
||||||
if (ccline.cmdbuff == NULL)
|
|
||||||
goto theend; // out of memory
|
goto theend; // out of memory
|
||||||
ccline.cmdlen = ccline.cmdpos = 0;
|
|
||||||
ccline.cmdbuff[0] = NUL;
|
|
||||||
sb_text_start_cmdline();
|
|
||||||
|
|
||||||
// autoindent for :insert and :append
|
|
||||||
if (firstc <= 0)
|
|
||||||
{
|
|
||||||
vim_memset(ccline.cmdbuff, ' ', indent);
|
|
||||||
ccline.cmdbuff[indent] = NUL;
|
|
||||||
ccline.cmdpos = indent;
|
|
||||||
ccline.cmdspos = indent;
|
|
||||||
ccline.cmdlen = indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpandInit(&xpc);
|
ExpandInit(&xpc);
|
||||||
ccline.xpc = &xpc;
|
ccline.xpc = &xpc;
|
||||||
@@ -1572,88 +1799,15 @@ getcmdline_int(
|
|||||||
// mode when 'insertmode' is set, CTRL-\ e prompts for an expression.
|
// mode when 'insertmode' is set, CTRL-\ e prompts for an expression.
|
||||||
if (c == Ctrl_BSL)
|
if (c == Ctrl_BSL)
|
||||||
{
|
{
|
||||||
++no_mapping;
|
res = cmdline_handle_backslash_key(c, &gotesc);
|
||||||
++allow_keys;
|
if (res == CMDLINE_CHANGED)
|
||||||
c = plain_vgetc();
|
goto cmdline_changed;
|
||||||
--no_mapping;
|
else if (res == CMDLINE_NOT_CHANGED)
|
||||||
--allow_keys;
|
|
||||||
// CTRL-\ e doesn't work when obtaining an expression, unless it
|
|
||||||
// is in a mapping.
|
|
||||||
if (c != Ctrl_N && c != Ctrl_G && (c != 'e'
|
|
||||||
|| (ccline.cmdfirstc == '=' && KeyTyped)
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
|| cmdline_star > 0
|
|
||||||
#endif
|
|
||||||
))
|
|
||||||
{
|
|
||||||
vungetc(c);
|
|
||||||
c = Ctrl_BSL;
|
|
||||||
}
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
else if (c == 'e')
|
|
||||||
{
|
|
||||||
char_u *p = NULL;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace the command line with the result of an expression.
|
|
||||||
* Need to save and restore the current command line, to be
|
|
||||||
* able to enter a new one...
|
|
||||||
*/
|
|
||||||
if (ccline.cmdpos == ccline.cmdlen)
|
|
||||||
new_cmdpos = 99999; // keep it at the end
|
|
||||||
else
|
|
||||||
new_cmdpos = ccline.cmdpos;
|
|
||||||
|
|
||||||
c = get_expr_register();
|
|
||||||
if (c == '=')
|
|
||||||
{
|
|
||||||
// Need to save and restore ccline. And set "textwinlock"
|
|
||||||
// to avoid nasty things like going to another buffer when
|
|
||||||
// evaluating an expression.
|
|
||||||
++textwinlock;
|
|
||||||
p = get_expr_line();
|
|
||||||
--textwinlock;
|
|
||||||
|
|
||||||
if (p != NULL)
|
|
||||||
{
|
|
||||||
len = (int)STRLEN(p);
|
|
||||||
if (realloc_cmdbuff(len + 1) == OK)
|
|
||||||
{
|
|
||||||
ccline.cmdlen = len;
|
|
||||||
STRCPY(ccline.cmdbuff, p);
|
|
||||||
vim_free(p);
|
|
||||||
|
|
||||||
// Restore the cursor or use the position set with
|
|
||||||
// set_cmdline_pos().
|
|
||||||
if (new_cmdpos > ccline.cmdlen)
|
|
||||||
ccline.cmdpos = ccline.cmdlen;
|
|
||||||
else
|
|
||||||
ccline.cmdpos = new_cmdpos;
|
|
||||||
|
|
||||||
KeyTyped = FALSE; // Don't do p_wc completion.
|
|
||||||
redrawcmd();
|
|
||||||
goto cmdline_changed;
|
|
||||||
}
|
|
||||||
vim_free(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
beep_flush();
|
|
||||||
got_int = FALSE; // don't abandon the command line
|
|
||||||
did_emsg = FALSE;
|
|
||||||
emsg_on_display = FALSE;
|
|
||||||
redrawcmd();
|
|
||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
}
|
else if (res == GOTO_NORMAL_MODE)
|
||||||
#endif
|
goto returncmd; // back to cmd mode
|
||||||
else
|
c = Ctrl_BSL; // backslash key not processed by
|
||||||
{
|
// cmdline_handle_backslash_key()
|
||||||
if (c == Ctrl_G && p_im && restart_edit == 0)
|
|
||||||
restart_edit = 'a';
|
|
||||||
gotesc = TRUE; // will free ccline.cmdbuff after putting it
|
|
||||||
// in history
|
|
||||||
goto returncmd; // back to Normal mode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_CMDWIN
|
#ifdef FEAT_CMDWIN
|
||||||
@@ -1705,115 +1859,12 @@ getcmdline_int(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Completion for 'wildchar' or 'wildcharm' key.
|
||||||
* Completion for 'wildchar' or 'wildcharm' key.
|
|
||||||
* - hitting <ESC> twice means: abandon command line.
|
|
||||||
* - wildcard expansion is only done when the 'wildchar' key is really
|
|
||||||
* typed, not when it comes from a macro
|
|
||||||
*/
|
|
||||||
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
|
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
|
||||||
{
|
{
|
||||||
int options = WILD_NO_BEEP;
|
res = cmdline_wildchar_complete(c, firstc != '@', &did_wild_list,
|
||||||
|
&wim_index, &xpc, &gotesc);
|
||||||
if (wim_flags[wim_index] & WIM_BUFLASTUSED)
|
if (res == CMDLINE_CHANGED)
|
||||||
options |= WILD_BUFLASTUSED;
|
|
||||||
if (xpc.xp_numfiles > 0) // typed p_wc at least twice
|
|
||||||
{
|
|
||||||
// if 'wildmode' contains "list" may still need to list
|
|
||||||
if (xpc.xp_numfiles > 1
|
|
||||||
&& !did_wild_list
|
|
||||||
&& (wim_flags[wim_index] & WIM_LIST))
|
|
||||||
{
|
|
||||||
(void)showmatches(&xpc, FALSE);
|
|
||||||
redrawcmd();
|
|
||||||
did_wild_list = TRUE;
|
|
||||||
}
|
|
||||||
if (wim_flags[wim_index] & WIM_LONGEST)
|
|
||||||
res = nextwild(&xpc, WILD_LONGEST, options,
|
|
||||||
firstc != '@');
|
|
||||||
else if (wim_flags[wim_index] & WIM_FULL)
|
|
||||||
res = nextwild(&xpc, WILD_NEXT, options, firstc != '@');
|
|
||||||
else
|
|
||||||
res = OK; // don't insert 'wildchar' now
|
|
||||||
}
|
|
||||||
else // typed p_wc first time
|
|
||||||
{
|
|
||||||
wim_index = 0;
|
|
||||||
j = ccline.cmdpos;
|
|
||||||
// if 'wildmode' first contains "longest", get longest
|
|
||||||
// common part
|
|
||||||
if (wim_flags[0] & WIM_LONGEST)
|
|
||||||
res = nextwild(&xpc, WILD_LONGEST, options, firstc != '@');
|
|
||||||
else
|
|
||||||
res = nextwild(&xpc, WILD_EXPAND_KEEP, options,
|
|
||||||
firstc != '@');
|
|
||||||
|
|
||||||
// if interrupted while completing, behave like it failed
|
|
||||||
if (got_int)
|
|
||||||
{
|
|
||||||
(void)vpeekc(); // remove <C-C> from input stream
|
|
||||||
got_int = FALSE; // don't abandon the command line
|
|
||||||
(void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
xpc.xp_context = EXPAND_NOTHING;
|
|
||||||
#endif
|
|
||||||
goto cmdline_changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when more than one match, and 'wildmode' first contains
|
|
||||||
// "list", or no change and 'wildmode' contains "longest,list",
|
|
||||||
// list all matches
|
|
||||||
if (res == OK && xpc.xp_numfiles > 1)
|
|
||||||
{
|
|
||||||
// a "longest" that didn't do anything is skipped (but not
|
|
||||||
// "list:longest")
|
|
||||||
if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j)
|
|
||||||
wim_index = 1;
|
|
||||||
if ((wim_flags[wim_index] & WIM_LIST)
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
|| (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!(wim_flags[0] & WIM_LONGEST))
|
|
||||||
{
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
int p_wmnu_save = p_wmnu;
|
|
||||||
p_wmnu = 0;
|
|
||||||
#endif
|
|
||||||
// remove match
|
|
||||||
nextwild(&xpc, WILD_PREV, 0, firstc != '@');
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
p_wmnu = p_wmnu_save;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
(void)showmatches(&xpc, p_wmnu
|
|
||||||
&& ((wim_flags[wim_index] & WIM_LIST) == 0));
|
|
||||||
#else
|
|
||||||
(void)showmatches(&xpc, FALSE);
|
|
||||||
#endif
|
|
||||||
redrawcmd();
|
|
||||||
did_wild_list = TRUE;
|
|
||||||
if (wim_flags[wim_index] & WIM_LONGEST)
|
|
||||||
nextwild(&xpc, WILD_LONGEST, options,
|
|
||||||
firstc != '@');
|
|
||||||
else if (wim_flags[wim_index] & WIM_FULL)
|
|
||||||
nextwild(&xpc, WILD_NEXT, options, firstc != '@');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vim_beep(BO_WILD);
|
|
||||||
}
|
|
||||||
#ifdef FEAT_WILDMENU
|
|
||||||
else if (xpc.xp_numfiles == -1)
|
|
||||||
xpc.xp_context = EXPAND_NOTHING;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (wim_index < 3)
|
|
||||||
++wim_index;
|
|
||||||
if (c == ESC)
|
|
||||||
gotesc = TRUE;
|
|
||||||
if (res == OK)
|
|
||||||
goto cmdline_changed;
|
goto cmdline_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -829,6 +829,15 @@ func Test_cmdline_complete_various()
|
|||||||
" completion after a range followed by a pipe (|) character
|
" completion after a range followed by a pipe (|) character
|
||||||
call feedkeys(":1,10 | chist\t\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":1,10 | chist\t\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"1,10 | chistory', @:)
|
call assert_equal('"1,10 | chistory', @:)
|
||||||
|
|
||||||
|
" use <Esc> as the 'wildchar' for completion
|
||||||
|
set wildchar=<Esc>
|
||||||
|
call feedkeys(":g/a\\xb/clearj\<Esc>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"g/a\xb/clearjumps', @:)
|
||||||
|
" pressing <esc> twice should cancel the command
|
||||||
|
call feedkeys(":chist\<Esc>\<Esc>", 'xt')
|
||||||
|
call assert_equal('"g/a\xb/clearjumps', @:)
|
||||||
|
set wildchar&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_cmdline_write_alternatefile()
|
func Test_cmdline_write_alternatefile()
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1634,
|
||||||
/**/
|
/**/
|
||||||
1633,
|
1633,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user