forked from aniani/vim
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
737
src/cmdexpand.c
737
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.
|
||||
* 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();
|
||||
int num_files;
|
||||
char_u **files_found;
|
||||
int i, j, k;
|
||||
int i, j;
|
||||
int maxlen;
|
||||
int lines;
|
||||
int columns;
|
||||
char_u *p;
|
||||
int lastlen;
|
||||
int attr;
|
||||
int showtail;
|
||||
|
||||
@@ -709,7 +799,6 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
||||
showtail = expand_showtail(xp);
|
||||
if (i != EXPAND_OK)
|
||||
return i;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -789,69 +878,8 @@ showmatches(expand_T *xp, int wildmenu UNUSED)
|
||||
// list the files line by line
|
||||
for (i = 0; i < lines; ++i)
|
||||
{
|
||||
lastlen = 999;
|
||||
for (k = i; k < num_files; k += lines)
|
||||
{
|
||||
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
|
||||
showmatches_oneline(xp, files_found, num_files, lines, i,
|
||||
maxlen, showtail, attr);
|
||||
if (got_int)
|
||||
{
|
||||
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'.
|
||||
* The argument to the command is 'arg' and the argument flags is 'argt'.
|
||||
@@ -1467,32 +1562,7 @@ set_context_by_cmdname(
|
||||
break;
|
||||
case CMD_and:
|
||||
case CMD_substitute:
|
||||
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;
|
||||
break;
|
||||
return find_cmd_after_substitute_cmd(arg);
|
||||
case CMD_isearch:
|
||||
case CMD_dsearch:
|
||||
case CMD_ilist:
|
||||
@@ -1502,26 +1572,7 @@ set_context_by_cmdname(
|
||||
case CMD_djump:
|
||||
case CMD_isplit:
|
||||
case CMD_dsplit:
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
return find_cmd_after_isearch_cmd(arg, xp);
|
||||
case CMD_autocmd:
|
||||
return set_context_in_autocmd(xp, arg, FALSE);
|
||||
case CMD_doautocmd:
|
||||
@@ -1652,36 +1703,8 @@ set_context_by_cmdname(
|
||||
#endif
|
||||
case CMD_USER:
|
||||
case CMD_USER_BUF:
|
||||
if (compl != EXPAND_NOTHING)
|
||||
{
|
||||
// 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;
|
||||
return set_context_in_user_cmdarg(cmd, arg, argt, compl, xp,
|
||||
forceit);
|
||||
|
||||
case CMD_map: case CMD_noremap:
|
||||
case CMD_nmap: case CMD_nnoremap:
|
||||
@@ -2312,6 +2335,31 @@ ExpandOther(
|
||||
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".
|
||||
*/
|
||||
@@ -2328,19 +2376,7 @@ ExpandFromContext(
|
||||
int flags;
|
||||
char_u *tofree = NULL;
|
||||
|
||||
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;
|
||||
flags = map_wildopts_to_ewflags(options);
|
||||
|
||||
if (xp->xp_context == EXPAND_FILES
|
||||
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||
@@ -2549,6 +2585,64 @@ ExpandGeneric(
|
||||
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.
|
||||
* Returns FAIL or OK;
|
||||
@@ -2569,11 +2663,8 @@ expand_shellcmd(
|
||||
size_t l;
|
||||
char_u *s, *e;
|
||||
int flags = flagsarg;
|
||||
int ret;
|
||||
int did_curdir = FALSE;
|
||||
hashtab_T found_ht;
|
||||
hashitem_T *hi;
|
||||
hash_T hash;
|
||||
|
||||
buf = alloc(MAXPATHL);
|
||||
if (buf == NULL)
|
||||
@@ -2640,42 +2731,10 @@ expand_shellcmd(
|
||||
l = e - s;
|
||||
if (l > MAXPATHL - 5)
|
||||
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.
|
||||
ret = expand_wildcards(1, &buf, num_file, file, flags);
|
||||
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];
|
||||
expand_shellcmd_onedir(buf, s, l, pat, file, num_file, flags,
|
||||
&found_ht, &ga);
|
||||
|
||||
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)
|
||||
++e;
|
||||
}
|
||||
@@ -2924,7 +2983,7 @@ wildmenu_translate_key(
|
||||
}
|
||||
#endif
|
||||
|
||||
if (did_wild_list && p_wmnu)
|
||||
if (did_wild_list)
|
||||
{
|
||||
if (c == K_LEFT)
|
||||
c = Ctrl_P;
|
||||
@@ -2933,7 +2992,7 @@ wildmenu_translate_key(
|
||||
}
|
||||
|
||||
// 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->cmdbuff[cclp->cmdpos - 1] == '.'
|
||||
&& cclp->cmdbuff[cclp->cmdpos - 2] != '\\'
|
||||
@@ -2957,170 +3016,188 @@ 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
|
||||
wildmenu_process_key(cmdline_info_T *cclp, int key, expand_T *xp)
|
||||
static int
|
||||
wildmenu_process_key_menunames(cmdline_info_T *cclp, int key, expand_T *xp)
|
||||
{
|
||||
int c = key;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (!p_wmnu)
|
||||
return c;
|
||||
|
||||
// Special translations for 'wildmenu'
|
||||
if (xp->xp_context == EXPAND_MENUNAMES)
|
||||
// Hitting <Down> after "emenu Name.": complete submenu
|
||||
if (key == K_DOWN && cclp->cmdpos > 0
|
||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.')
|
||||
{
|
||||
// Hitting <Down> after "emenu Name.": complete submenu
|
||||
if (c == K_DOWN && cclp->cmdpos > 0
|
||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.')
|
||||
{
|
||||
c = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
}
|
||||
else if (c == K_UP)
|
||||
{
|
||||
// Hitting <Up>: Remove one submenu name in front of the
|
||||
// cursor
|
||||
int found = FALSE;
|
||||
key = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
}
|
||||
else if (key == K_UP)
|
||||
{
|
||||
// Hitting <Up>: Remove one submenu name in front of the
|
||||
// cursor
|
||||
int found = FALSE;
|
||||
|
||||
j = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
i = 0;
|
||||
while (--j > 0)
|
||||
j = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
i = 0;
|
||||
while (--j > 0)
|
||||
{
|
||||
// check for start of menu name
|
||||
if (cclp->cmdbuff[j] == ' '
|
||||
&& cclp->cmdbuff[j - 1] != '\\')
|
||||
{
|
||||
// check for start of menu name
|
||||
if (cclp->cmdbuff[j] == ' '
|
||||
&& cclp->cmdbuff[j - 1] != '\\')
|
||||
i = j + 1;
|
||||
break;
|
||||
}
|
||||
// check for start of submenu name
|
||||
if (cclp->cmdbuff[j] == '.'
|
||||
&& cclp->cmdbuff[j - 1] != '\\')
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
i = j + 1;
|
||||
break;
|
||||
}
|
||||
// check for start of submenu name
|
||||
if (cclp->cmdbuff[j] == '.'
|
||||
&& cclp->cmdbuff[j - 1] != '\\')
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
i = j + 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
found = TRUE;
|
||||
}
|
||||
else
|
||||
found = TRUE;
|
||||
}
|
||||
if (i > 0)
|
||||
cmdline_del(cclp, i);
|
||||
c = p_wc;
|
||||
}
|
||||
if (i > 0)
|
||||
cmdline_del(cclp, i);
|
||||
key = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
|
||||
upseg[0] = PATHSEP;
|
||||
upseg[1] = '.';
|
||||
upseg[2] = '.';
|
||||
upseg[3] = PATHSEP;
|
||||
upseg[4] = NUL;
|
||||
|
||||
if (key == K_DOWN
|
||||
&& cclp->cmdpos > 0
|
||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
|
||||
&& (cclp->cmdpos < 3
|
||||
|| cclp->cmdbuff[cclp->cmdpos - 2] != '.'
|
||||
|| cclp->cmdbuff[cclp->cmdpos - 3] != '.'))
|
||||
{
|
||||
// go down a directory
|
||||
key = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
}
|
||||
else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && key == K_DOWN)
|
||||
{
|
||||
// If in a direct ancestor, strip off one ../ to go down
|
||||
int found = FALSE;
|
||||
|
||||
j = cclp->cmdpos;
|
||||
i = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
while (--j > i)
|
||||
{
|
||||
if (has_mbyte)
|
||||
j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||
if (vim_ispathsep(cclp->cmdbuff[j]))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found
|
||||
&& cclp->cmdbuff[j - 1] == '.'
|
||||
&& cclp->cmdbuff[j - 2] == '.'
|
||||
&& (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2))
|
||||
{
|
||||
cmdline_del(cclp, j - 2);
|
||||
key = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
if ((xp->xp_context == EXPAND_FILES
|
||||
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||
|| xp->xp_context == EXPAND_SHELLCMD))
|
||||
else if (key == K_UP)
|
||||
{
|
||||
char_u upseg[5];
|
||||
// go up a directory
|
||||
int found = FALSE;
|
||||
|
||||
upseg[0] = PATHSEP;
|
||||
upseg[1] = '.';
|
||||
upseg[2] = '.';
|
||||
upseg[3] = PATHSEP;
|
||||
upseg[4] = NUL;
|
||||
|
||||
if (c == K_DOWN
|
||||
&& cclp->cmdpos > 0
|
||||
&& cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
|
||||
&& (cclp->cmdpos < 3
|
||||
|| cclp->cmdbuff[cclp->cmdpos - 2] != '.'
|
||||
|| cclp->cmdbuff[cclp->cmdpos - 3] != '.'))
|
||||
j = cclp->cmdpos - 1;
|
||||
i = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
while (--j > i)
|
||||
{
|
||||
// go down a directory
|
||||
c = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
}
|
||||
else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
|
||||
{
|
||||
// If in a direct ancestor, strip off one ../ to go down
|
||||
int found = FALSE;
|
||||
|
||||
j = cclp->cmdpos;
|
||||
i = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
while (--j > i)
|
||||
if (has_mbyte)
|
||||
j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||
if (vim_ispathsep(cclp->cmdbuff[j])
|
||||
# ifdef BACKSLASH_IN_FILENAME
|
||||
&& vim_strchr((char_u *)" *?[{`$%#",
|
||||
cclp->cmdbuff[j + 1]) == NULL
|
||||
# endif
|
||||
)
|
||||
{
|
||||
if (has_mbyte)
|
||||
j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||
if (vim_ispathsep(cclp->cmdbuff[j]))
|
||||
if (found)
|
||||
{
|
||||
found = TRUE;
|
||||
i = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found
|
||||
&& cclp->cmdbuff[j - 1] == '.'
|
||||
&& cclp->cmdbuff[j - 2] == '.'
|
||||
&& (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2))
|
||||
{
|
||||
cmdline_del(cclp, j - 2);
|
||||
c = p_wc;
|
||||
KeyTyped = TRUE; // in case the key was mapped
|
||||
else
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
else if (c == K_UP)
|
||||
|
||||
if (!found)
|
||||
j = i;
|
||||
else if (STRNCMP(cclp->cmdbuff + j, upseg, 4) == 0)
|
||||
j += 4;
|
||||
else if (STRNCMP(cclp->cmdbuff + j, upseg + 1, 3) == 0
|
||||
&& j == i)
|
||||
j += 3;
|
||||
else
|
||||
j = 0;
|
||||
if (j > 0)
|
||||
{
|
||||
// go up a directory
|
||||
int found = FALSE;
|
||||
|
||||
j = cclp->cmdpos - 1;
|
||||
i = (int)(xp->xp_pattern - cclp->cmdbuff);
|
||||
while (--j > i)
|
||||
{
|
||||
if (has_mbyte)
|
||||
j -= (*mb_head_off)(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||
if (vim_ispathsep(cclp->cmdbuff[j])
|
||||
# ifdef BACKSLASH_IN_FILENAME
|
||||
&& vim_strchr((char_u *)" *?[{`$%#",
|
||||
cclp->cmdbuff[j + 1]) == NULL
|
||||
# endif
|
||||
)
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
i = j + 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
j = i;
|
||||
else if (STRNCMP(cclp->cmdbuff + j, upseg, 4) == 0)
|
||||
j += 4;
|
||||
else if (STRNCMP(cclp->cmdbuff + j, upseg + 1, 3) == 0
|
||||
&& j == i)
|
||||
j += 3;
|
||||
else
|
||||
j = 0;
|
||||
if (j > 0)
|
||||
{
|
||||
// TODO this is only for DOS/UNIX systems - need to put in
|
||||
// machine-specific stuff here and in upseg init
|
||||
cmdline_del(cclp, j);
|
||||
put_on_cmdline(upseg + 1, 3, FALSE);
|
||||
}
|
||||
else if (cclp->cmdpos > i)
|
||||
cmdline_del(cclp, i);
|
||||
|
||||
// Now complete in the new directory. Set KeyTyped in case the
|
||||
// Up key came from a mapping.
|
||||
c = p_wc;
|
||||
KeyTyped = TRUE;
|
||||
// TODO this is only for DOS/UNIX systems - need to put in
|
||||
// machine-specific stuff here and in upseg init
|
||||
cmdline_del(cclp, j);
|
||||
put_on_cmdline(upseg + 1, 3, FALSE);
|
||||
}
|
||||
else if (cclp->cmdpos > i)
|
||||
cmdline_del(cclp, i);
|
||||
|
||||
// Now complete in the new directory. Set KeyTyped in case the
|
||||
// Up key came from a mapping.
|
||||
key = p_wc;
|
||||
KeyTyped = TRUE;
|
||||
}
|
||||
|
||||
return c;
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user