mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 8.2.4398: some command completion functions are too long
Problem: Some command completion functions are too long. Solution: Refactor code into separate functions. Add a few more tests. (Yegappan Lakshmanan, closes #9785)
This commit is contained in:
committed by
Bram Moolenaar
parent
34f8117dec
commit
b31aec3b93
515
src/cmdexpand.c
515
src/cmdexpand.c
@@ -681,6 +681,98 @@ ExpandCleanup(expand_T *xp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display one line of completion matches. Multiple matches are displayed in
|
||||||
|
* each line (used by wildmode=list and CTRL-D)
|
||||||
|
* files_found - list of completion match names
|
||||||
|
* num_files - number of completion matches in "files_found"
|
||||||
|
* lines - number of output lines
|
||||||
|
* linenr - line number of matches to display
|
||||||
|
* maxlen - maximum number of characters in each line
|
||||||
|
* showtail - display only the tail of the full path of a file name
|
||||||
|
* dir_attr - highlight attribute to use for directory names
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
showmatches_oneline(
|
||||||
|
expand_T *xp,
|
||||||
|
char_u **files_found,
|
||||||
|
int num_files,
|
||||||
|
int lines,
|
||||||
|
int linenr,
|
||||||
|
int maxlen,
|
||||||
|
int showtail,
|
||||||
|
int dir_attr)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int isdir;
|
||||||
|
int lastlen;
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
lastlen = 999;
|
||||||
|
for (j = linenr; j < num_files; j += lines)
|
||||||
|
{
|
||||||
|
if (xp->xp_context == EXPAND_TAGS_LISTFILES)
|
||||||
|
{
|
||||||
|
msg_outtrans_attr(files_found[j], HL_ATTR(HLF_D));
|
||||||
|
p = files_found[j] + STRLEN(files_found[j]) + 1;
|
||||||
|
msg_advance(maxlen + 1);
|
||||||
|
msg_puts((char *)p);
|
||||||
|
msg_advance(maxlen + 3);
|
||||||
|
msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = maxlen - lastlen; --i >= 0; )
|
||||||
|
msg_putchar(' ');
|
||||||
|
if (xp->xp_context == EXPAND_FILES
|
||||||
|
|| xp->xp_context == EXPAND_SHELLCMD
|
||||||
|
|| xp->xp_context == EXPAND_BUFFERS)
|
||||||
|
{
|
||||||
|
// highlight directories
|
||||||
|
if (xp->xp_numfiles != -1)
|
||||||
|
{
|
||||||
|
char_u *halved_slash;
|
||||||
|
char_u *exp_path;
|
||||||
|
char_u *path;
|
||||||
|
|
||||||
|
// Expansion was done before and special characters
|
||||||
|
// were escaped, need to halve backslashes. Also
|
||||||
|
// $HOME has been replaced with ~/.
|
||||||
|
exp_path = expand_env_save_opt(files_found[j], TRUE);
|
||||||
|
path = exp_path != NULL ? exp_path : files_found[j];
|
||||||
|
halved_slash = backslash_halve_save(path);
|
||||||
|
isdir = mch_isdir(halved_slash != NULL ? halved_slash
|
||||||
|
: files_found[j]);
|
||||||
|
vim_free(exp_path);
|
||||||
|
if (halved_slash != path)
|
||||||
|
vim_free(halved_slash);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Expansion was done here, file names are literal.
|
||||||
|
isdir = mch_isdir(files_found[j]);
|
||||||
|
if (showtail)
|
||||||
|
p = SHOW_FILE_TEXT(j);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
home_replace(NULL, files_found[j], NameBuff, MAXPATHL,
|
||||||
|
TRUE);
|
||||||
|
p = NameBuff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isdir = FALSE;
|
||||||
|
p = SHOW_FILE_TEXT(j);
|
||||||
|
}
|
||||||
|
lastlen = msg_outtrans_attr(p, isdir ? dir_attr : 0);
|
||||||
|
}
|
||||||
|
if (msg_col > 0) // when not wrapped around
|
||||||
|
{
|
||||||
|
msg_clr_eos();
|
||||||
|
msg_putchar('\n');
|
||||||
|
}
|
||||||
|
out_flush(); // show one line at a time
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show all matches for completion on the command line.
|
* Show all matches for completion on the command line.
|
||||||
* Returns EXPAND_NOTHING when the character that triggered expansion should
|
* Returns EXPAND_NOTHING when the character that triggered expansion should
|
||||||
@@ -692,12 +784,10 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
cmdline_info_T *ccline = get_cmdline_info();
|
cmdline_info_T *ccline = get_cmdline_info();
|
||||||
int num_files;
|
int num_files;
|
||||||
char_u **files_found;
|
char_u **files_found;
|
||||||
int i, j, k;
|
int i, j;
|
||||||
int maxlen;
|
int maxlen;
|
||||||
int lines;
|
int lines;
|
||||||
int columns;
|
int columns;
|
||||||
char_u *p;
|
|
||||||
int lastlen;
|
|
||||||
int attr;
|
int attr;
|
||||||
int showtail;
|
int showtail;
|
||||||
|
|
||||||
@@ -709,7 +799,6 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
showtail = expand_showtail(xp);
|
showtail = expand_showtail(xp);
|
||||||
if (i != EXPAND_OK)
|
if (i != EXPAND_OK)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -789,69 +878,8 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
|||||||
// list the files line by line
|
// list the files line by line
|
||||||
for (i = 0; i < lines; ++i)
|
for (i = 0; i < lines; ++i)
|
||||||
{
|
{
|
||||||
lastlen = 999;
|
showmatches_oneline(xp, files_found, num_files, lines, i,
|
||||||
for (k = i; k < num_files; k += lines)
|
maxlen, showtail, attr);
|
||||||
{
|
|
||||||
if (xp->xp_context == EXPAND_TAGS_LISTFILES)
|
|
||||||
{
|
|
||||||
msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D));
|
|
||||||
p = files_found[k] + STRLEN(files_found[k]) + 1;
|
|
||||||
msg_advance(maxlen + 1);
|
|
||||||
msg_puts((char *)p);
|
|
||||||
msg_advance(maxlen + 3);
|
|
||||||
msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (j = maxlen - lastlen; --j >= 0; )
|
|
||||||
msg_putchar(' ');
|
|
||||||
if (xp->xp_context == EXPAND_FILES
|
|
||||||
|| xp->xp_context == EXPAND_SHELLCMD
|
|
||||||
|| xp->xp_context == EXPAND_BUFFERS)
|
|
||||||
{
|
|
||||||
// highlight directories
|
|
||||||
if (xp->xp_numfiles != -1)
|
|
||||||
{
|
|
||||||
char_u *halved_slash;
|
|
||||||
char_u *exp_path;
|
|
||||||
char_u *path;
|
|
||||||
|
|
||||||
// Expansion was done before and special characters
|
|
||||||
// were escaped, need to halve backslashes. Also
|
|
||||||
// $HOME has been replaced with ~/.
|
|
||||||
exp_path = expand_env_save_opt(files_found[k], TRUE);
|
|
||||||
path = exp_path != NULL ? exp_path : files_found[k];
|
|
||||||
halved_slash = backslash_halve_save(path);
|
|
||||||
j = mch_isdir(halved_slash != NULL ? halved_slash
|
|
||||||
: files_found[k]);
|
|
||||||
vim_free(exp_path);
|
|
||||||
if (halved_slash != path)
|
|
||||||
vim_free(halved_slash);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// Expansion was done here, file names are literal.
|
|
||||||
j = mch_isdir(files_found[k]);
|
|
||||||
if (showtail)
|
|
||||||
p = SHOW_FILE_TEXT(k);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
home_replace(NULL, files_found[k], NameBuff, MAXPATHL,
|
|
||||||
TRUE);
|
|
||||||
p = NameBuff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
j = FALSE;
|
|
||||||
p = SHOW_FILE_TEXT(k);
|
|
||||||
}
|
|
||||||
lastlen = msg_outtrans_attr(p, j ? attr : 0);
|
|
||||||
}
|
|
||||||
if (msg_col > 0) // when not wrapped around
|
|
||||||
{
|
|
||||||
msg_clr_eos();
|
|
||||||
msg_putchar('\n');
|
|
||||||
}
|
|
||||||
out_flush(); // show one line at a time
|
|
||||||
if (got_int)
|
if (got_int)
|
||||||
{
|
{
|
||||||
got_int = FALSE;
|
got_int = FALSE;
|
||||||
@@ -1333,6 +1361,73 @@ set_context_for_wildcard_arg(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to the next command after a :substitute or a :& command.
|
||||||
|
* Returns NULL if there is no next command.
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
find_cmd_after_substitute_cmd(char_u *arg)
|
||||||
|
{
|
||||||
|
int delim;
|
||||||
|
|
||||||
|
delim = *arg;
|
||||||
|
if (delim)
|
||||||
|
{
|
||||||
|
// skip "from" part
|
||||||
|
++arg;
|
||||||
|
arg = skip_regexp(arg, delim, magic_isset());
|
||||||
|
|
||||||
|
if (arg[0] != NUL && arg[0] == delim)
|
||||||
|
{
|
||||||
|
// skip "to" part
|
||||||
|
++arg;
|
||||||
|
while (arg[0] != NUL && arg[0] != delim)
|
||||||
|
{
|
||||||
|
if (arg[0] == '\\' && arg[1] != NUL)
|
||||||
|
++arg;
|
||||||
|
++arg;
|
||||||
|
}
|
||||||
|
if (arg[0] != NUL) // skip delimiter
|
||||||
|
++arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
|
||||||
|
++arg;
|
||||||
|
if (arg[0] != NUL)
|
||||||
|
return arg;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to the next command after a :isearch/:dsearch/:ilist
|
||||||
|
* :dlist/:ijump/:psearch/:djump/:isplit/:dsplit command.
|
||||||
|
* Returns NULL if there is no next command.
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
find_cmd_after_isearch_cmd(char_u *arg, expand_T *xp)
|
||||||
|
{
|
||||||
|
arg = skipwhite(skipdigits(arg)); // skip count
|
||||||
|
if (*arg == '/') // Match regexp, not just whole words
|
||||||
|
{
|
||||||
|
for (++arg; *arg && *arg != '/'; arg++)
|
||||||
|
if (*arg == '\\' && arg[1] != NUL)
|
||||||
|
arg++;
|
||||||
|
if (*arg)
|
||||||
|
{
|
||||||
|
arg = skipwhite(arg + 1);
|
||||||
|
|
||||||
|
// Check for trailing illegal characters
|
||||||
|
if (*arg == NUL || vim_strchr((char_u *)"|\"\n", *arg) == NULL)
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
else
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the completion context in 'xp' for command 'cmd' with index 'cmdidx'.
|
* Set the completion context in 'xp' for command 'cmd' with index 'cmdidx'.
|
||||||
* The argument to the command is 'arg' and the argument flags is 'argt'.
|
* The argument to the command is 'arg' and the argument flags is 'argt'.
|
||||||
@@ -1467,32 +1562,7 @@ set_context_by_cmdname(
|
|||||||
break;
|
break;
|
||||||
case CMD_and:
|
case CMD_and:
|
||||||
case CMD_substitute:
|
case CMD_substitute:
|
||||||
delim = *arg;
|
return find_cmd_after_substitute_cmd(arg);
|
||||||
if (delim)
|
|
||||||
{
|
|
||||||
// skip "from" part
|
|
||||||
++arg;
|
|
||||||
arg = skip_regexp(arg, delim, magic_isset());
|
|
||||||
|
|
||||||
if (arg[0] != NUL && arg[0] == delim)
|
|
||||||
{
|
|
||||||
// skip "to" part
|
|
||||||
++arg;
|
|
||||||
while (arg[0] != NUL && arg[0] != delim)
|
|
||||||
{
|
|
||||||
if (arg[0] == '\\' && arg[1] != NUL)
|
|
||||||
++arg;
|
|
||||||
++arg;
|
|
||||||
}
|
|
||||||
if (arg[0] != NUL) // skip delimiter
|
|
||||||
++arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
|
|
||||||
++arg;
|
|
||||||
if (arg[0] != NUL)
|
|
||||||
return arg;
|
|
||||||
break;
|
|
||||||
case CMD_isearch:
|
case CMD_isearch:
|
||||||
case CMD_dsearch:
|
case CMD_dsearch:
|
||||||
case CMD_ilist:
|
case CMD_ilist:
|
||||||
@@ -1502,26 +1572,7 @@ set_context_by_cmdname(
|
|||||||
case CMD_djump:
|
case CMD_djump:
|
||||||
case CMD_isplit:
|
case CMD_isplit:
|
||||||
case CMD_dsplit:
|
case CMD_dsplit:
|
||||||
arg = skipwhite(skipdigits(arg)); // skip count
|
return find_cmd_after_isearch_cmd(arg, xp);
|
||||||
if (*arg == '/') // Match regexp, not just whole words
|
|
||||||
{
|
|
||||||
for (++arg; *arg && *arg != '/'; arg++)
|
|
||||||
if (*arg == '\\' && arg[1] != NUL)
|
|
||||||
arg++;
|
|
||||||
if (*arg)
|
|
||||||
{
|
|
||||||
arg = skipwhite(arg + 1);
|
|
||||||
|
|
||||||
// Check for trailing illegal characters
|
|
||||||
if (*arg == NUL ||
|
|
||||||
vim_strchr((char_u *)"|\"\n", *arg) == NULL)
|
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
|
||||||
else
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_autocmd:
|
case CMD_autocmd:
|
||||||
return set_context_in_autocmd(xp, arg, FALSE);
|
return set_context_in_autocmd(xp, arg, FALSE);
|
||||||
case CMD_doautocmd:
|
case CMD_doautocmd:
|
||||||
@@ -1652,36 +1703,8 @@ set_context_by_cmdname(
|
|||||||
#endif
|
#endif
|
||||||
case CMD_USER:
|
case CMD_USER:
|
||||||
case CMD_USER_BUF:
|
case CMD_USER_BUF:
|
||||||
if (compl != EXPAND_NOTHING)
|
return set_context_in_user_cmdarg(cmd, arg, argt, compl, xp,
|
||||||
{
|
forceit);
|
||||||
// EX_XFILE: file names are handled above
|
|
||||||
if (!(argt & EX_XFILE))
|
|
||||||
{
|
|
||||||
#ifdef FEAT_MENU
|
|
||||||
if (compl == EXPAND_MENUS)
|
|
||||||
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
|
||||||
#endif
|
|
||||||
if (compl == EXPAND_COMMANDS)
|
|
||||||
return arg;
|
|
||||||
if (compl == EXPAND_MAPPINGS)
|
|
||||||
return set_context_in_map_cmd(xp, (char_u *)"map",
|
|
||||||
arg, forceit, FALSE, FALSE, CMD_map);
|
|
||||||
// Find start of last argument.
|
|
||||||
p = arg;
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
if (*p == ' ')
|
|
||||||
// argument starts after a space
|
|
||||||
arg = p + 1;
|
|
||||||
else if (*p == '\\' && *(p + 1) != NUL)
|
|
||||||
++p; // skip over escaped character
|
|
||||||
MB_PTR_ADV(p);
|
|
||||||
}
|
|
||||||
xp->xp_pattern = arg;
|
|
||||||
}
|
|
||||||
xp->xp_context = compl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_map: case CMD_noremap:
|
case CMD_map: case CMD_noremap:
|
||||||
case CMD_nmap: case CMD_nnoremap:
|
case CMD_nmap: case CMD_nnoremap:
|
||||||
@@ -2312,6 +2335,31 @@ ExpandOther(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map wild expand options to flags for expand_wildcards()
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
map_wildopts_to_ewflags(int options)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = EW_DIR; // include directories
|
||||||
|
if (options & WILD_LIST_NOTFOUND)
|
||||||
|
flags |= EW_NOTFOUND;
|
||||||
|
if (options & WILD_ADD_SLASH)
|
||||||
|
flags |= EW_ADDSLASH;
|
||||||
|
if (options & WILD_KEEP_ALL)
|
||||||
|
flags |= EW_KEEPALL;
|
||||||
|
if (options & WILD_SILENT)
|
||||||
|
flags |= EW_SILENT;
|
||||||
|
if (options & WILD_NOERROR)
|
||||||
|
flags |= EW_NOERROR;
|
||||||
|
if (options & WILD_ALLLINKS)
|
||||||
|
flags |= EW_ALLLINKS;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the expansion based on xp->xp_context and "pat".
|
* Do the expansion based on xp->xp_context and "pat".
|
||||||
*/
|
*/
|
||||||
@@ -2328,19 +2376,7 @@ ExpandFromContext(
|
|||||||
int flags;
|
int flags;
|
||||||
char_u *tofree = NULL;
|
char_u *tofree = NULL;
|
||||||
|
|
||||||
flags = EW_DIR; // include directories
|
flags = map_wildopts_to_ewflags(options);
|
||||||
if (options & WILD_LIST_NOTFOUND)
|
|
||||||
flags |= EW_NOTFOUND;
|
|
||||||
if (options & WILD_ADD_SLASH)
|
|
||||||
flags |= EW_ADDSLASH;
|
|
||||||
if (options & WILD_KEEP_ALL)
|
|
||||||
flags |= EW_KEEPALL;
|
|
||||||
if (options & WILD_SILENT)
|
|
||||||
flags |= EW_SILENT;
|
|
||||||
if (options & WILD_NOERROR)
|
|
||||||
flags |= EW_NOERROR;
|
|
||||||
if (options & WILD_ALLLINKS)
|
|
||||||
flags |= EW_ALLLINKS;
|
|
||||||
|
|
||||||
if (xp->xp_context == EXPAND_FILES
|
if (xp->xp_context == EXPAND_FILES
|
||||||
|| xp->xp_context == EXPAND_DIRECTORIES
|
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||||
@@ -2549,6 +2585,64 @@ ExpandGeneric(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand shell command matches in one directory of $PATH.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
expand_shellcmd_onedir(
|
||||||
|
char_u *buf,
|
||||||
|
char_u *s,
|
||||||
|
size_t l,
|
||||||
|
char_u *pat,
|
||||||
|
char_u ***files,
|
||||||
|
int *num_files,
|
||||||
|
int flags,
|
||||||
|
hashtab_T *ht,
|
||||||
|
garray_T *gap)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
hash_T hash;
|
||||||
|
hashitem_T *hi;
|
||||||
|
|
||||||
|
vim_strncpy(buf, s, l);
|
||||||
|
add_pathsep(buf);
|
||||||
|
l = STRLEN(buf);
|
||||||
|
vim_strncpy(buf + l, pat, MAXPATHL - 1 - l);
|
||||||
|
|
||||||
|
// Expand matches in one directory of $PATH.
|
||||||
|
ret = expand_wildcards(1, &buf, num_files, files, flags);
|
||||||
|
if (ret == OK)
|
||||||
|
{
|
||||||
|
if (ga_grow(gap, *num_files) == FAIL)
|
||||||
|
FreeWild(*num_files, *files);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < *num_files; ++i)
|
||||||
|
{
|
||||||
|
char_u *name = (*files)[i];
|
||||||
|
|
||||||
|
if (STRLEN(name) > l)
|
||||||
|
{
|
||||||
|
// Check if this name was already found.
|
||||||
|
hash = hash_hash(name + l);
|
||||||
|
hi = hash_lookup(ht, name + l, hash);
|
||||||
|
if (HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
// Remove the path that was prepended.
|
||||||
|
STRMOVE(name, name + l);
|
||||||
|
((char_u **)gap->ga_data)[gap->ga_len++] = name;
|
||||||
|
hash_add_item(ht, hi, name, hash);
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vim_free(name);
|
||||||
|
}
|
||||||
|
vim_free(*files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Complete a shell command.
|
* Complete a shell command.
|
||||||
* Returns FAIL or OK;
|
* Returns FAIL or OK;
|
||||||
@@ -2569,11 +2663,8 @@ expand_shellcmd(
|
|||||||
size_t l;
|
size_t l;
|
||||||
char_u *s, *e;
|
char_u *s, *e;
|
||||||
int flags = flagsarg;
|
int flags = flagsarg;
|
||||||
int ret;
|
|
||||||
int did_curdir = FALSE;
|
int did_curdir = FALSE;
|
||||||
hashtab_T found_ht;
|
hashtab_T found_ht;
|
||||||
hashitem_T *hi;
|
|
||||||
hash_T hash;
|
|
||||||
|
|
||||||
buf = alloc(MAXPATHL);
|
buf = alloc(MAXPATHL);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
@@ -2640,42 +2731,10 @@ expand_shellcmd(
|
|||||||
l = e - s;
|
l = e - s;
|
||||||
if (l > MAXPATHL - 5)
|
if (l > MAXPATHL - 5)
|
||||||
break;
|
break;
|
||||||
vim_strncpy(buf, s, l);
|
|
||||||
add_pathsep(buf);
|
|
||||||
l = STRLEN(buf);
|
|
||||||
vim_strncpy(buf + l, pat, MAXPATHL - 1 - l);
|
|
||||||
|
|
||||||
// Expand matches in one directory of $PATH.
|
expand_shellcmd_onedir(buf, s, l, pat, file, num_file, flags,
|
||||||
ret = expand_wildcards(1, &buf, num_file, file, flags);
|
&found_ht, &ga);
|
||||||
if (ret == OK)
|
|
||||||
{
|
|
||||||
if (ga_grow(&ga, *num_file) == FAIL)
|
|
||||||
FreeWild(*num_file, *file);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < *num_file; ++i)
|
|
||||||
{
|
|
||||||
char_u *name = (*file)[i];
|
|
||||||
|
|
||||||
if (STRLEN(name) > l)
|
|
||||||
{
|
|
||||||
// Check if this name was already found.
|
|
||||||
hash = hash_hash(name + l);
|
|
||||||
hi = hash_lookup(&found_ht, name + l, hash);
|
|
||||||
if (HASHITEM_EMPTY(hi))
|
|
||||||
{
|
|
||||||
// Remove the path that was prepended.
|
|
||||||
STRMOVE(name, name + l);
|
|
||||||
((char_u **)ga.ga_data)[ga.ga_len++] = name;
|
|
||||||
hash_add_item(&found_ht, hi, name, hash);
|
|
||||||
name = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vim_free(name);
|
|
||||||
}
|
|
||||||
vim_free(*file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*e != NUL)
|
if (*e != NUL)
|
||||||
++e;
|
++e;
|
||||||
}
|
}
|
||||||
@@ -2924,7 +2983,7 @@ wildmenu_translate_key(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (did_wild_list && p_wmnu)
|
if (did_wild_list)
|
||||||
{
|
{
|
||||||
if (c == K_LEFT)
|
if (c == K_LEFT)
|
||||||
c = Ctrl_P;
|
c = Ctrl_P;
|
||||||
@@ -2933,7 +2992,7 @@ wildmenu_translate_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hitting CR after "emenu Name.": complete submenu
|
// Hitting CR after "emenu Name.": complete submenu
|
||||||
if (xp->xp_context == EXPAND_MENUNAMES && p_wmnu
|
if (xp->xp_context == EXPAND_MENUNAMES
|
||||||
&& cclp->cmdpos > 1
|
&& cclp->cmdpos > 1
|
||||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.'
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.'
|
||||||
&& cclp->cmdbuff[cclp->cmdpos - 2] != '\\'
|
&& cclp->cmdbuff[cclp->cmdpos - 2] != '\\'
|
||||||
@@ -2957,29 +3016,23 @@ cmdline_del(cmdline_info_T *cclp, int from)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a key pressed when wild menu is displayed
|
* Handle a key pressed when the wild menu for the menu names
|
||||||
|
* (EXPAND_MENUNAMES) is displayed.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
wildmenu_process_key_menunames(cmdline_info_T *cclp, int key, expand_T *xp)
|
||||||
{
|
{
|
||||||
int c = key;
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (!p_wmnu)
|
|
||||||
return c;
|
|
||||||
|
|
||||||
// Special translations for 'wildmenu'
|
|
||||||
if (xp->xp_context == EXPAND_MENUNAMES)
|
|
||||||
{
|
|
||||||
// Hitting <Down> after "emenu Name.": complete submenu
|
// Hitting <Down> after "emenu Name.": complete submenu
|
||||||
if (c == K_DOWN && cclp->cmdpos > 0
|
if (key == K_DOWN && cclp->cmdpos > 0
|
||||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.')
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.')
|
||||||
{
|
{
|
||||||
c = p_wc;
|
key = p_wc;
|
||||||
KeyTyped = TRUE; // in case the key was mapped
|
KeyTyped = TRUE; // in case the key was mapped
|
||||||
}
|
}
|
||||||
else if (c == K_UP)
|
else if (key == K_UP)
|
||||||
{
|
{
|
||||||
// Hitting <Up>: Remove one submenu name in front of the
|
// Hitting <Up>: Remove one submenu name in front of the
|
||||||
// cursor
|
// cursor
|
||||||
@@ -3011,15 +3064,24 @@ wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
|||||||
}
|
}
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
cmdline_del(cclp, i);
|
cmdline_del(cclp, i);
|
||||||
c = p_wc;
|
key = p_wc;
|
||||||
KeyTyped = TRUE; // in case the key was mapped
|
KeyTyped = TRUE; // in case the key was mapped
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
if ((xp->xp_context == EXPAND_FILES
|
|
||||||
|| xp->xp_context == EXPAND_DIRECTORIES
|
/*
|
||||||
|| xp->xp_context == EXPAND_SHELLCMD))
|
* Handle a key pressed when the wild menu for file names (EXPAND_FILES) or
|
||||||
|
* directory names (EXPAND_DIRECTORIES) or shell command names
|
||||||
|
* (EXPAND_SHELLCMD) is displayed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
wildmenu_process_key_filenames(cmdline_info_T *cclp, int key, expand_T *xp)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
char_u upseg[5];
|
char_u upseg[5];
|
||||||
|
|
||||||
upseg[0] = PATHSEP;
|
upseg[0] = PATHSEP;
|
||||||
@@ -3028,7 +3090,7 @@ wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
|||||||
upseg[3] = PATHSEP;
|
upseg[3] = PATHSEP;
|
||||||
upseg[4] = NUL;
|
upseg[4] = NUL;
|
||||||
|
|
||||||
if (c == K_DOWN
|
if (key == K_DOWN
|
||||||
&& cclp->cmdpos > 0
|
&& cclp->cmdpos > 0
|
||||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
|
||||||
&& (cclp->cmdpos < 3
|
&& (cclp->cmdpos < 3
|
||||||
@@ -3036,10 +3098,10 @@ wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
|||||||
|| cclp->cmdbuff[cclp->cmdpos - 3] != '.'))
|
|| cclp->cmdbuff[cclp->cmdpos - 3] != '.'))
|
||||||
{
|
{
|
||||||
// go down a directory
|
// go down a directory
|
||||||
c = p_wc;
|
key = p_wc;
|
||||||
KeyTyped = TRUE; // in case the key was mapped
|
KeyTyped = TRUE; // in case the key was mapped
|
||||||
}
|
}
|
||||||
else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
|
else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && key == K_DOWN)
|
||||||
{
|
{
|
||||||
// If in a direct ancestor, strip off one ../ to go down
|
// If in a direct ancestor, strip off one ../ to go down
|
||||||
int found = FALSE;
|
int found = FALSE;
|
||||||
@@ -3062,11 +3124,11 @@ wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
|||||||
&& (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2))
|
&& (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2))
|
||||||
{
|
{
|
||||||
cmdline_del(cclp, j - 2);
|
cmdline_del(cclp, j - 2);
|
||||||
c = p_wc;
|
key = p_wc;
|
||||||
KeyTyped = TRUE; // in case the key was mapped
|
KeyTyped = TRUE; // in case the key was mapped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == K_UP)
|
else if (key == K_UP)
|
||||||
{
|
{
|
||||||
// go up a directory
|
// go up a directory
|
||||||
int found = FALSE;
|
int found = FALSE;
|
||||||
@@ -3115,12 +3177,27 @@ wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
|||||||
|
|
||||||
// Now complete in the new directory. Set KeyTyped in case the
|
// Now complete in the new directory. Set KeyTyped in case the
|
||||||
// Up key came from a mapping.
|
// Up key came from a mapping.
|
||||||
c = p_wc;
|
key = p_wc;
|
||||||
KeyTyped = TRUE;
|
KeyTyped = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
/*
|
||||||
|
* Handle a key pressed when the wild menu is displayed
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
||||||
|
{
|
||||||
|
if (xp->xp_context == EXPAND_MENUNAMES)
|
||||||
|
return wildmenu_process_key_menunames(cclp, key, xp);
|
||||||
|
else if ((xp->xp_context == EXPAND_FILES
|
||||||
|
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||||
|
|| xp->xp_context == EXPAND_SHELLCMD))
|
||||||
|
return wildmenu_process_key_filenames(cclp, key, xp);
|
||||||
|
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1856,6 +1856,7 @@ getcmdline_int(
|
|||||||
c = Ctrl_P;
|
c = Ctrl_P;
|
||||||
|
|
||||||
#ifdef FEAT_WILDMENU
|
#ifdef FEAT_WILDMENU
|
||||||
|
if (p_wmnu)
|
||||||
c = wildmenu_translate_key(&ccline, c, &xpc, did_wild_list);
|
c = wildmenu_translate_key(&ccline, c, &xpc, did_wild_list);
|
||||||
|
|
||||||
if (cmdline_pum_active())
|
if (cmdline_pum_active())
|
||||||
@@ -1900,6 +1901,7 @@ getcmdline_int(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_WILDMENU
|
#ifdef FEAT_WILDMENU
|
||||||
|
if (p_wmnu)
|
||||||
c = wildmenu_process_key(&ccline, c, &xpc);
|
c = wildmenu_process_key(&ccline, c, &xpc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* usercmd.c */
|
/* usercmd.c */
|
||||||
char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *complp);
|
char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *complp);
|
||||||
|
char_u *set_context_in_user_cmdarg(char_u *cmd, char_u *arg, long argt, int compl, expand_T *xp, int forceit);
|
||||||
char_u *set_context_in_user_cmd(expand_T *xp, char_u *arg_in);
|
char_u *set_context_in_user_cmd(expand_T *xp, char_u *arg_in);
|
||||||
char_u *expand_user_command_name(int idx);
|
char_u *expand_user_command_name(int idx);
|
||||||
char_u *get_user_commands(expand_T *xp, int idx);
|
char_u *get_user_commands(expand_T *xp, int idx);
|
||||||
|
@@ -53,9 +53,13 @@ func Test_complete_list()
|
|||||||
set completeslash=backslash
|
set completeslash=backslash
|
||||||
call feedkeys(":e Xtest\<Tab>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e Xtest\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e Xtest\', @:)
|
call assert_equal('"e Xtest\', @:)
|
||||||
|
call feedkeys(":e Xtest/\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"e Xtest\a.', @:)
|
||||||
set completeslash=slash
|
set completeslash=slash
|
||||||
call feedkeys(":e Xtest\<Tab>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e Xtest\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e Xtest/', @:)
|
call assert_equal('"e Xtest/', @:)
|
||||||
|
call feedkeys(":e Xtest\\\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"e Xtest/a.', @:)
|
||||||
set completeslash&
|
set completeslash&
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -139,6 +143,7 @@ func Test_complete_wildmenu()
|
|||||||
call assert_equal('"e Xtestfile3 Xtestfile4', @:)
|
call assert_equal('"e Xtestfile3 Xtestfile4', @:)
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
|
" test for wildmenumode()
|
||||||
cnoremap <expr> <F2> wildmenumode()
|
cnoremap <expr> <F2> wildmenumode()
|
||||||
call feedkeys(":cd Xdir\<Tab>\<F2>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":cd Xdir\<Tab>\<F2>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"cd Xdir1/0', @:)
|
call assert_equal('"cd Xdir1/0', @:)
|
||||||
@@ -148,12 +153,7 @@ func Test_complete_wildmenu()
|
|||||||
|
|
||||||
" cleanup
|
" cleanup
|
||||||
%bwipe
|
%bwipe
|
||||||
call delete('Xdir1/Xdir2/Xtestfile4')
|
call delete('Xdir1', 'rf')
|
||||||
call delete('Xdir1/Xdir2/Xtestfile3')
|
|
||||||
call delete('Xdir1/Xtestfile2')
|
|
||||||
call delete('Xdir1/Xtestfile1')
|
|
||||||
call delete('Xdir1/Xdir2', 'd')
|
|
||||||
call delete('Xdir1', 'd')
|
|
||||||
set nowildmenu
|
set nowildmenu
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -1100,6 +1100,10 @@ func Test_cmdline_complete_various()
|
|||||||
call feedkeys(":e Xx\*\<Tab>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e Xx\*\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e Xx\*Yy', @:)
|
call assert_equal('"e Xx\*Yy', @:)
|
||||||
call delete('Xx*Yy')
|
call delete('Xx*Yy')
|
||||||
|
|
||||||
|
" use a literal star
|
||||||
|
call feedkeys(":e \\*\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"e \*', @:)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call feedkeys(":py3f\<Tab>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":py3f\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
@@ -2005,28 +2009,34 @@ endfunc
|
|||||||
func Test_wildmenu_dirstack()
|
func Test_wildmenu_dirstack()
|
||||||
CheckUnix
|
CheckUnix
|
||||||
%bw!
|
%bw!
|
||||||
call mkdir('Xdir1/dir2/dir3', 'p')
|
call mkdir('Xdir1/dir2/dir3/dir4', 'p')
|
||||||
call writefile([], 'Xdir1/file1_1.txt')
|
call writefile([], 'Xdir1/file1_1.txt')
|
||||||
call writefile([], 'Xdir1/file1_2.txt')
|
call writefile([], 'Xdir1/file1_2.txt')
|
||||||
call writefile([], 'Xdir1/dir2/file2_1.txt')
|
call writefile([], 'Xdir1/dir2/file2_1.txt')
|
||||||
call writefile([], 'Xdir1/dir2/file2_2.txt')
|
call writefile([], 'Xdir1/dir2/file2_2.txt')
|
||||||
call writefile([], 'Xdir1/dir2/dir3/file3_1.txt')
|
call writefile([], 'Xdir1/dir2/dir3/file3_1.txt')
|
||||||
call writefile([], 'Xdir1/dir2/dir3/file3_2.txt')
|
call writefile([], 'Xdir1/dir2/dir3/file3_2.txt')
|
||||||
cd Xdir1/dir2/dir3
|
call writefile([], 'Xdir1/dir2/dir3/dir4/file4_1.txt')
|
||||||
|
call writefile([], 'Xdir1/dir2/dir3/dir4/file4_2.txt')
|
||||||
set wildmenu
|
set wildmenu
|
||||||
|
|
||||||
|
cd Xdir1/dir2/dir3/dir4
|
||||||
call feedkeys(":e \<Tab>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e file3_1.txt', @:)
|
call assert_equal('"e file4_1.txt', @:)
|
||||||
call feedkeys(":e \<Tab>\<Up>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e \<Tab>\<Up>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e ../dir3/', @:)
|
call assert_equal('"e ../dir4/', @:)
|
||||||
call feedkeys(":e \<Tab>\<Up>\<Up>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e \<Tab>\<Up>\<Up>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e ../../dir2/', @:)
|
call assert_equal('"e ../../dir3/', @:)
|
||||||
|
call feedkeys(":e \<Tab>\<Up>\<Up>\<Up>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"e ../../../dir2/', @:)
|
||||||
call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e ../../dir2/dir3/', @:)
|
call assert_equal('"e ../../dir3/dir4/', @:)
|
||||||
call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<Down>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<Down>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal('"e ../../dir2/dir3/file3_1.txt', @:)
|
call assert_equal('"e ../../dir3/dir4/file4_1.txt', @:)
|
||||||
|
|
||||||
cd -
|
cd -
|
||||||
|
call feedkeys(":e Xdir1/\<Tab>\<Down>\<Down>\<Down>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"e Xdir1/dir2/dir3/dir4/file4_1.txt', @:)
|
||||||
|
|
||||||
call delete('Xdir1', 'rf')
|
call delete('Xdir1', 'rf')
|
||||||
set wildmenu&
|
set wildmenu&
|
||||||
endfunc
|
endfunc
|
||||||
|
@@ -231,6 +231,9 @@ find_ucmd(
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set completion context for :command
|
||||||
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
set_context_in_user_cmd(expand_T *xp, char_u *arg_in)
|
set_context_in_user_cmd(expand_T *xp, char_u *arg_in)
|
||||||
{
|
{
|
||||||
@@ -292,6 +295,56 @@ set_context_in_user_cmd(expand_T *xp, char_u *arg_in)
|
|||||||
return skipwhite(p);
|
return skipwhite(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the completion context for the argument of a user defined command.
|
||||||
|
*/
|
||||||
|
char_u *
|
||||||
|
set_context_in_user_cmdarg(
|
||||||
|
char_u *cmd UNUSED,
|
||||||
|
char_u *arg,
|
||||||
|
long argt,
|
||||||
|
int compl,
|
||||||
|
expand_T *xp,
|
||||||
|
int forceit)
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
if (compl == EXPAND_NOTHING)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (argt & EX_XFILE)
|
||||||
|
{
|
||||||
|
// EX_XFILE: file names are handled before this call
|
||||||
|
xp->xp_context = compl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_MENU
|
||||||
|
if (compl == EXPAND_MENUS)
|
||||||
|
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
||||||
|
#endif
|
||||||
|
if (compl == EXPAND_COMMANDS)
|
||||||
|
return arg;
|
||||||
|
if (compl == EXPAND_MAPPINGS)
|
||||||
|
return set_context_in_map_cmd(xp, (char_u *)"map", arg, forceit, FALSE,
|
||||||
|
FALSE, CMD_map);
|
||||||
|
// Find start of last argument.
|
||||||
|
p = arg;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
if (*p == ' ')
|
||||||
|
// argument starts after a space
|
||||||
|
arg = p + 1;
|
||||||
|
else if (*p == '\\' && *(p + 1) != NUL)
|
||||||
|
++p; // skip over escaped character
|
||||||
|
MB_PTR_ADV(p);
|
||||||
|
}
|
||||||
|
xp->xp_pattern = arg;
|
||||||
|
xp->xp_context = compl;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char_u *
|
char_u *
|
||||||
expand_user_command_name(int idx)
|
expand_user_command_name(int idx)
|
||||||
{
|
{
|
||||||
|
@@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
4398,
|
||||||
/**/
|
/**/
|
||||||
4397,
|
4397,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user