mirror of
https://github.com/neovim/neovim.git
synced 2025-09-22 19:18:34 +00:00
vim-patch:8.2.4406: expand functions use confusing argument names (#21800)
Problem: Expand functions use confusing argument names.
Solution: Rename "file" to "match". Refactor some completion code. Add a
few more tests. (Yegappan Lakshmanan, closes vim/vim#9790)
2438430863
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
@@ -90,9 +90,11 @@ static int compl_startcol;
|
|||||||
static int compl_selected;
|
static int compl_selected;
|
||||||
|
|
||||||
#define SHOW_FILE_TEXT(m) (showtail \
|
#define SHOW_FILE_TEXT(m) (showtail \
|
||||||
? showmatches_gettail(files_found[m], false) \
|
? showmatches_gettail(matches[m], false) \
|
||||||
: files_found[m])
|
: matches[m])
|
||||||
|
|
||||||
|
/// Sort function for the completion matches.
|
||||||
|
/// <SNR> functions should be sorted to the end.
|
||||||
static int sort_func_compare(const void *s1, const void *s2)
|
static int sort_func_compare(const void *s1, const void *s2)
|
||||||
{
|
{
|
||||||
char *p1 = *(char **)s1;
|
char *p1 = *(char **)s1;
|
||||||
@@ -284,15 +286,15 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create and display a cmdline completion popup menu with items from
|
/// Create and display a cmdline completion popup menu with items from
|
||||||
/// "files_found".
|
/// "matches".
|
||||||
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **files_found, int num_files,
|
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
|
||||||
int showtail)
|
int showtail)
|
||||||
{
|
{
|
||||||
assert(num_files >= 0);
|
assert(numMatches >= 0);
|
||||||
// Add all the completion matches
|
// Add all the completion matches
|
||||||
compl_match_arraysize = num_files;
|
compl_match_arraysize = numMatches;
|
||||||
compl_match_array = xmalloc(sizeof(pumitem_T) * (size_t)compl_match_arraysize);
|
compl_match_array = xmalloc(sizeof(pumitem_T) * (size_t)compl_match_arraysize);
|
||||||
for (int i = 0; i < num_files; i++) {
|
for (int i = 0; i < numMatches; i++) {
|
||||||
compl_match_array[i] = (pumitem_T){
|
compl_match_array[i] = (pumitem_T){
|
||||||
.pum_text = SHOW_FILE_TEXT(i),
|
.pum_text = SHOW_FILE_TEXT(i),
|
||||||
.pum_info = NULL,
|
.pum_info = NULL,
|
||||||
@@ -628,7 +630,7 @@ static char *ExpandOne_start(int mode, expand_T *xp, char *str, int options)
|
|||||||
char *ss = NULL;
|
char *ss = NULL;
|
||||||
|
|
||||||
// Do the expansion.
|
// Do the expansion.
|
||||||
if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, options) == FAIL) {
|
if (ExpandFromContext(xp, str, &xp->xp_files, &xp->xp_numfiles, options) == FAIL) {
|
||||||
#ifdef FNAME_ILLEGAL
|
#ifdef FNAME_ILLEGAL
|
||||||
// Illegal file name has been silently skipped. But when there
|
// Illegal file name has been silently skipped. But when there
|
||||||
// are wildcards, the real problem is that there was no match,
|
// are wildcards, the real problem is that there was no match,
|
||||||
@@ -646,8 +648,7 @@ static char *ExpandOne_start(int mode, expand_T *xp, char *str, int options)
|
|||||||
ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
|
ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options);
|
||||||
|
|
||||||
// Check for matching suffixes in file names.
|
// Check for matching suffixes in file names.
|
||||||
if (mode != WILD_ALL && mode != WILD_ALL_KEEP
|
if (mode != WILD_ALL && mode != WILD_ALL_KEEP && mode != WILD_LONGEST) {
|
||||||
&& mode != WILD_LONGEST) {
|
|
||||||
if (xp->xp_numfiles) {
|
if (xp->xp_numfiles) {
|
||||||
non_suf_match = xp->xp_numfiles;
|
non_suf_match = xp->xp_numfiles;
|
||||||
} else {
|
} else {
|
||||||
@@ -862,22 +863,22 @@ void ExpandCleanup(expand_T *xp)
|
|||||||
/// Display one line of completion matches. Multiple matches are displayed in
|
/// Display one line of completion matches. Multiple matches are displayed in
|
||||||
/// each line (used by wildmode=list and CTRL-D)
|
/// each line (used by wildmode=list and CTRL-D)
|
||||||
///
|
///
|
||||||
/// @param files_found list of completion match names
|
/// @param matches list of completion match names
|
||||||
/// @param num_files number of completion matches in "files_found"
|
/// @param numMatches number of completion matches in "matches"
|
||||||
/// @param lines number of output lines
|
/// @param lines number of output lines
|
||||||
/// @param linenr line number of matches to display
|
/// @param linenr line number of matches to display
|
||||||
/// @param maxlen maximum number of characters in each line
|
/// @param maxlen maximum number of characters in each line
|
||||||
/// @param showtail display only the tail of the full path of a file name
|
/// @param showtail display only the tail of the full path of a file name
|
||||||
/// @param dir_attr highlight attribute to use for directory names
|
/// @param dir_attr highlight attribute to use for directory names
|
||||||
static void showmatches_oneline(expand_T *xp, char **files_found, int num_files, int lines,
|
static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, int lines, int linenr,
|
||||||
int linenr, int maxlen, int showtail, int dir_attr)
|
int maxlen, int showtail, int dir_attr)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int lastlen = 999;
|
int lastlen = 999;
|
||||||
for (int j = linenr; j < num_files; j += lines) {
|
for (int j = linenr; j < numMatches; j += lines) {
|
||||||
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
||||||
msg_outtrans_attr(files_found[j], HL_ATTR(HLF_D));
|
msg_outtrans_attr(matches[j], HL_ATTR(HLF_D));
|
||||||
p = files_found[j] + strlen(files_found[j]) + 1;
|
p = matches[j] + strlen(matches[j]) + 1;
|
||||||
msg_advance(maxlen + 1);
|
msg_advance(maxlen + 1);
|
||||||
msg_puts((const char *)p);
|
msg_puts((const char *)p);
|
||||||
msg_advance(maxlen + 3);
|
msg_advance(maxlen + 3);
|
||||||
@@ -896,8 +897,8 @@ static void showmatches_oneline(expand_T *xp, char **files_found, int num_files,
|
|||||||
// Expansion was done before and special characters
|
// Expansion was done before and special characters
|
||||||
// were escaped, need to halve backslashes. Also
|
// were escaped, need to halve backslashes. Also
|
||||||
// $HOME has been replaced with ~/.
|
// $HOME has been replaced with ~/.
|
||||||
char *exp_path = (char *)expand_env_save_opt(files_found[j], true);
|
char *exp_path = (char *)expand_env_save_opt(matches[j], true);
|
||||||
char *path = exp_path != NULL ? exp_path : files_found[j];
|
char *path = exp_path != NULL ? exp_path : matches[j];
|
||||||
char *halved_slash = backslash_halve_save(path);
|
char *halved_slash = backslash_halve_save(path);
|
||||||
isdir = os_isdir(halved_slash);
|
isdir = os_isdir(halved_slash);
|
||||||
xfree(exp_path);
|
xfree(exp_path);
|
||||||
@@ -906,12 +907,12 @@ static void showmatches_oneline(expand_T *xp, char **files_found, int num_files,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Expansion was done here, file names are literal.
|
// Expansion was done here, file names are literal.
|
||||||
isdir = os_isdir(files_found[j]);
|
isdir = os_isdir(matches[j]);
|
||||||
}
|
}
|
||||||
if (showtail) {
|
if (showtail) {
|
||||||
p = SHOW_FILE_TEXT(j);
|
p = SHOW_FILE_TEXT(j);
|
||||||
} else {
|
} else {
|
||||||
home_replace(NULL, files_found[j], NameBuff, MAXPATHL, true);
|
home_replace(NULL, matches[j], NameBuff, MAXPATHL, true);
|
||||||
p = NameBuff;
|
p = NameBuff;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -932,8 +933,8 @@ static void showmatches_oneline(expand_T *xp, char **files_found, int num_files,
|
|||||||
int showmatches(expand_T *xp, int wildmenu)
|
int showmatches(expand_T *xp, int wildmenu)
|
||||||
{
|
{
|
||||||
CmdlineInfo *const ccline = get_cmdline_info();
|
CmdlineInfo *const ccline = get_cmdline_info();
|
||||||
int num_files;
|
int numMatches;
|
||||||
char **files_found;
|
char **matches;
|
||||||
int i, j;
|
int i, j;
|
||||||
int maxlen;
|
int maxlen;
|
||||||
int lines;
|
int lines;
|
||||||
@@ -944,14 +945,14 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
if (xp->xp_numfiles == -1) {
|
if (xp->xp_numfiles == -1) {
|
||||||
set_expand_context(xp);
|
set_expand_context(xp);
|
||||||
i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
|
i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
|
||||||
&num_files, &files_found);
|
&numMatches, &matches);
|
||||||
showtail = expand_showtail(xp);
|
showtail = expand_showtail(xp);
|
||||||
if (i != EXPAND_OK) {
|
if (i != EXPAND_OK) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
num_files = xp->xp_numfiles;
|
numMatches = xp->xp_numfiles;
|
||||||
files_found = xp->xp_files;
|
matches = xp->xp_files;
|
||||||
showtail = cmd_showtail;
|
showtail = cmd_showtail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,7 +963,7 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
|
|
||||||
if (compl_use_pum) {
|
if (compl_use_pum) {
|
||||||
// cmdline completion popup menu (with wildoptions=pum)
|
// cmdline completion popup menu (with wildoptions=pum)
|
||||||
return cmdline_pum_create(ccline, xp, files_found, num_files, showtail);
|
return cmdline_pum_create(ccline, xp, matches, numMatches, showtail);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wildmenu) {
|
if (!wildmenu) {
|
||||||
@@ -978,15 +979,15 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
if (got_int) {
|
if (got_int) {
|
||||||
got_int = false; // only int. the completion, not the cmd line
|
got_int = false; // only int. the completion, not the cmd line
|
||||||
} else if (wildmenu) {
|
} else if (wildmenu) {
|
||||||
redraw_wildmenu(xp, num_files, files_found, -1, showtail);
|
redraw_wildmenu(xp, numMatches, matches, -1, showtail);
|
||||||
} else {
|
} else {
|
||||||
// find the length of the longest file name
|
// find the length of the longest file name
|
||||||
maxlen = 0;
|
maxlen = 0;
|
||||||
for (i = 0; i < num_files; i++) {
|
for (i = 0; i < numMatches; i++) {
|
||||||
if (!showtail && (xp->xp_context == EXPAND_FILES
|
if (!showtail && (xp->xp_context == EXPAND_FILES
|
||||||
|| xp->xp_context == EXPAND_SHELLCMD
|
|| xp->xp_context == EXPAND_SHELLCMD
|
||||||
|| xp->xp_context == EXPAND_BUFFERS)) {
|
|| xp->xp_context == EXPAND_BUFFERS)) {
|
||||||
home_replace(NULL, files_found[i], NameBuff, MAXPATHL, true);
|
home_replace(NULL, matches[i], NameBuff, MAXPATHL, true);
|
||||||
j = vim_strsize(NameBuff);
|
j = vim_strsize(NameBuff);
|
||||||
} else {
|
} else {
|
||||||
j = vim_strsize(SHOW_FILE_TEXT(i));
|
j = vim_strsize(SHOW_FILE_TEXT(i));
|
||||||
@@ -997,7 +998,7 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
||||||
lines = num_files;
|
lines = numMatches;
|
||||||
} else {
|
} else {
|
||||||
// compute the number of columns and lines for the listing
|
// compute the number of columns and lines for the listing
|
||||||
maxlen += 2; // two spaces between file names
|
maxlen += 2; // two spaces between file names
|
||||||
@@ -1005,7 +1006,7 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
if (columns < 1) {
|
if (columns < 1) {
|
||||||
columns = 1;
|
columns = 1;
|
||||||
}
|
}
|
||||||
lines = (num_files + columns - 1) / columns;
|
lines = (numMatches + columns - 1) / columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = HL_ATTR(HLF_D); // find out highlighting for directories
|
attr = HL_ATTR(HLF_D); // find out highlighting for directories
|
||||||
@@ -1019,7 +1020,7 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
|
|
||||||
// list the files line by line
|
// list the files line by line
|
||||||
for (i = 0; i < lines; i++) {
|
for (i = 0; i < lines; i++) {
|
||||||
showmatches_oneline(xp, files_found, num_files, lines, i, maxlen, showtail, attr);
|
showmatches_oneline(xp, matches, numMatches, lines, i, maxlen, showtail, attr);
|
||||||
if (got_int) {
|
if (got_int) {
|
||||||
got_int = false;
|
got_int = false;
|
||||||
break;
|
break;
|
||||||
@@ -1032,7 +1033,7 @@ int showmatches(expand_T *xp, int wildmenu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (xp->xp_numfiles == -1) {
|
if (xp->xp_numfiles == -1) {
|
||||||
FreeWild(num_files, files_found);
|
FreeWild(numMatches, matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXPAND_OK;
|
return EXPAND_OK;
|
||||||
@@ -1457,6 +1458,58 @@ static void set_context_for_wildcard_arg(exarg_T *eap, const char *arg, bool use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the completion context for the :filter command. Returns a pointer to the
|
||||||
|
/// next command after the :filter command.
|
||||||
|
static const char *set_context_in_filter_cmd(expand_T *xp, const char *arg)
|
||||||
|
{
|
||||||
|
if (*arg != NUL) {
|
||||||
|
arg = (const char *)skip_vimgrep_pat((char *)arg, NULL, NULL);
|
||||||
|
}
|
||||||
|
if (arg == NULL || *arg == NUL) {
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (const char *)skipwhite(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the completion context for the :match command. Returns a pointer to the
|
||||||
|
/// next command after the :match command.
|
||||||
|
static const char *set_context_in_match_cmd(expand_T *xp, const char *arg)
|
||||||
|
{
|
||||||
|
if (*arg == NUL || !ends_excmd(*arg)) {
|
||||||
|
// also complete "None"
|
||||||
|
set_context_in_echohl_cmd(xp, arg);
|
||||||
|
arg = (const char *)skipwhite(skiptowhite(arg));
|
||||||
|
if (*arg != NUL) {
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
arg = (const char *)skip_regexp((char *)arg + 1, (uint8_t)(*arg), magic_isset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (const char *)find_nextcmd(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a pointer to the next command after a :global or a :v command.
|
||||||
|
/// Returns NULL if there is no next command.
|
||||||
|
static const char *find_cmd_after_global_cmd(const char *arg)
|
||||||
|
{
|
||||||
|
const int delim = (uint8_t)(*arg); // Get the delimiter.
|
||||||
|
if (delim) {
|
||||||
|
arg++; // Skip delimiter if there is one.
|
||||||
|
}
|
||||||
|
|
||||||
|
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
||||||
|
if (arg[0] == '\\' && arg[1] != NUL) {
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
if (arg[0] != NUL) {
|
||||||
|
return arg + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a pointer to the next command after a :substitute or a :& command.
|
/// Returns a pointer to the next command after a :substitute or a :& command.
|
||||||
/// Returns NULL if there is no next command.
|
/// Returns NULL if there is no next command.
|
||||||
static const char *find_cmd_after_substitute_cmd(const char *arg)
|
static const char *find_cmd_after_substitute_cmd(const char *arg)
|
||||||
@@ -1494,7 +1547,7 @@ static const char *find_cmd_after_substitute_cmd(const char *arg)
|
|||||||
/// Returns a pointer to the next command after a :isearch/:dsearch/:ilist
|
/// Returns a pointer to the next command after a :isearch/:dsearch/:ilist
|
||||||
/// :dlist/:ijump/:psearch/:djump/:isplit/:dsplit command.
|
/// :dlist/:ijump/:psearch/:djump/:isplit/:dsplit command.
|
||||||
/// Returns NULL if there is no next command.
|
/// Returns NULL if there is no next command.
|
||||||
static const char *find_cmd_after_isearch_cmd(const char *arg, expand_T *xp)
|
static const char *find_cmd_after_isearch_cmd(expand_T *xp, const char *arg)
|
||||||
{
|
{
|
||||||
// Skip count.
|
// Skip count.
|
||||||
arg = (const char *)skipwhite(skipdigits(arg));
|
arg = (const char *)skipwhite(skipdigits(arg));
|
||||||
@@ -1522,17 +1575,55 @@ static const char *find_cmd_after_isearch_cmd(const char *arg, expand_T *xp)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the completion context for the :unlet command. Always returns NULL.
|
||||||
|
static const char *set_context_in_unlet_cmd(expand_T *xp, const char *arg)
|
||||||
|
{
|
||||||
|
while ((xp->xp_pattern = strchr(arg, ' ')) != NULL) {
|
||||||
|
arg = (const char *)xp->xp_pattern + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xp->xp_context = EXPAND_USER_VARS;
|
||||||
|
xp->xp_pattern = (char *)arg;
|
||||||
|
|
||||||
|
if (*xp->xp_pattern == '$') {
|
||||||
|
xp->xp_context = EXPAND_ENV_VARS;
|
||||||
|
xp->xp_pattern++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the completion context for the :language command. Always returns NULL.
|
||||||
|
static const char *set_context_in_lang_cmd(expand_T *xp, const char *arg)
|
||||||
|
{
|
||||||
|
const char *p = (const char *)skiptowhite(arg);
|
||||||
|
if (*p == NUL) {
|
||||||
|
xp->xp_context = EXPAND_LANGUAGE;
|
||||||
|
xp->xp_pattern = (char *)arg;
|
||||||
|
} else {
|
||||||
|
if (strncmp(arg, "messages", (size_t)(p - arg)) == 0
|
||||||
|
|| strncmp(arg, "ctype", (size_t)(p - arg)) == 0
|
||||||
|
|| strncmp(arg, "time", (size_t)(p - arg)) == 0
|
||||||
|
|| strncmp(arg, "collate", (size_t)(p - arg)) == 0) {
|
||||||
|
xp->xp_context = EXPAND_LOCALES;
|
||||||
|
xp->xp_pattern = skipwhite(p);
|
||||||
|
} else {
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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".
|
||||||
/// For user-defined commands and for environment variables, "context" has the
|
/// For user-defined commands and for environment variables, "context" has the
|
||||||
/// completion type.
|
/// completion type.
|
||||||
///
|
///
|
||||||
/// @return a pointer to the next command, or NULL if there is no next command.
|
/// @return a pointer to the next command, or NULL if there is no next command.
|
||||||
static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, const char *arg,
|
static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expand_T *xp,
|
||||||
uint32_t argt, int context, expand_T *xp, bool forceit)
|
const char *arg, uint32_t argt, int context, bool forceit)
|
||||||
{
|
{
|
||||||
const char *p;
|
|
||||||
|
|
||||||
switch (cmdidx) {
|
switch (cmdidx) {
|
||||||
case CMD_find:
|
case CMD_find:
|
||||||
case CMD_sfind:
|
case CMD_sfind:
|
||||||
@@ -1594,26 +1685,10 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
|
|||||||
return arg;
|
return arg;
|
||||||
|
|
||||||
case CMD_filter:
|
case CMD_filter:
|
||||||
if (*arg != NUL) {
|
return set_context_in_filter_cmd(xp, arg);
|
||||||
arg = (const char *)skip_vimgrep_pat((char *)arg, NULL, NULL);
|
|
||||||
}
|
|
||||||
if (arg == NULL || *arg == NUL) {
|
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (const char *)skipwhite(arg);
|
|
||||||
|
|
||||||
case CMD_match:
|
case CMD_match:
|
||||||
if (*arg == NUL || !ends_excmd(*arg)) {
|
return set_context_in_match_cmd(xp, arg);
|
||||||
// also complete "None"
|
|
||||||
set_context_in_echohl_cmd(xp, arg);
|
|
||||||
arg = (const char *)skipwhite(skiptowhite(arg));
|
|
||||||
if (*arg != NUL) {
|
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
|
||||||
arg = (const char *)skip_regexp((char *)arg + 1, (uint8_t)(*arg), magic_isset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (const char *)find_nextcmd(arg);
|
|
||||||
|
|
||||||
// All completion for the +cmdline_compl feature goes here.
|
// All completion for the +cmdline_compl feature goes here.
|
||||||
|
|
||||||
@@ -1626,23 +1701,8 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_global:
|
case CMD_global:
|
||||||
case CMD_vglobal: {
|
case CMD_vglobal:
|
||||||
const int delim = (uint8_t)(*arg); // Get the delimiter.
|
return find_cmd_after_global_cmd(arg);
|
||||||
if (delim) {
|
|
||||||
arg++; // Skip delimiter if there is one.
|
|
||||||
}
|
|
||||||
|
|
||||||
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
|
||||||
if (arg[0] == '\\' && arg[1] != NUL) {
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
arg++;
|
|
||||||
}
|
|
||||||
if (arg[0] != NUL) {
|
|
||||||
return arg + 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CMD_and:
|
case CMD_and:
|
||||||
case CMD_substitute:
|
case CMD_substitute:
|
||||||
return find_cmd_after_substitute_cmd(arg);
|
return find_cmd_after_substitute_cmd(arg);
|
||||||
@@ -1655,7 +1715,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
|
|||||||
case CMD_djump:
|
case CMD_djump:
|
||||||
case CMD_isplit:
|
case CMD_isplit:
|
||||||
case CMD_dsplit:
|
case CMD_dsplit:
|
||||||
return find_cmd_after_isearch_cmd(arg, xp);
|
return find_cmd_after_isearch_cmd(xp, arg);
|
||||||
case CMD_autocmd:
|
case CMD_autocmd:
|
||||||
return (const char *)set_context_in_autocmd(xp, (char *)arg, false);
|
return (const char *)set_context_in_autocmd(xp, (char *)arg, false);
|
||||||
|
|
||||||
@@ -1718,20 +1778,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_unlet:
|
case CMD_unlet:
|
||||||
while ((xp->xp_pattern = strchr(arg, ' ')) != NULL) {
|
return set_context_in_unlet_cmd(xp, arg);
|
||||||
arg = (const char *)xp->xp_pattern + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
xp->xp_context = EXPAND_USER_VARS;
|
|
||||||
xp->xp_pattern = (char *)arg;
|
|
||||||
|
|
||||||
if (*xp->xp_pattern == '$') {
|
|
||||||
xp->xp_context = EXPAND_ENV_VARS;
|
|
||||||
xp->xp_pattern++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_function:
|
case CMD_function:
|
||||||
case CMD_delfunction:
|
case CMD_delfunction:
|
||||||
xp->xp_context = EXPAND_USER_FUNC;
|
xp->xp_context = EXPAND_USER_FUNC;
|
||||||
@@ -1886,22 +1933,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons
|
|||||||
|
|
||||||
#ifdef HAVE_WORKING_LIBINTL
|
#ifdef HAVE_WORKING_LIBINTL
|
||||||
case CMD_language:
|
case CMD_language:
|
||||||
p = (const char *)skiptowhite(arg);
|
return set_context_in_lang_cmd(xp, arg);
|
||||||
if (*p == NUL) {
|
|
||||||
xp->xp_context = EXPAND_LANGUAGE;
|
|
||||||
xp->xp_pattern = (char *)arg;
|
|
||||||
} else {
|
|
||||||
if (strncmp(arg, "messages", (size_t)(p - arg)) == 0
|
|
||||||
|| strncmp(arg, "ctype", (size_t)(p - arg)) == 0
|
|
||||||
|| strncmp(arg, "time", (size_t)(p - arg)) == 0
|
|
||||||
|| strncmp(arg, "collate", (size_t)(p - arg)) == 0) {
|
|
||||||
xp->xp_context = EXPAND_LOCALES;
|
|
||||||
xp->xp_pattern = skipwhite(p);
|
|
||||||
} else {
|
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case CMD_profile:
|
case CMD_profile:
|
||||||
set_context_in_profile_cmd(xp, arg);
|
set_context_in_profile_cmd(xp, arg);
|
||||||
@@ -2120,9 +2152,11 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Switch on command name.
|
// Switch on command name.
|
||||||
return set_context_by_cmdname(cmd, ea.cmdidx, arg, ea.argt, context, xp, forceit);
|
return set_context_by_cmdname(cmd, ea.cmdidx, xp, arg, ea.argt, context, forceit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the completion context in "xp" for command "str"
|
||||||
|
///
|
||||||
/// @param str start of command line
|
/// @param str start of command line
|
||||||
/// @param len length of command line (excl. NUL)
|
/// @param len length of command line (excl. NUL)
|
||||||
/// @param col position of cursor
|
/// @param col position of cursor
|
||||||
@@ -2199,7 +2233,7 @@ int expand_cmdline(expand_T *xp, const char *str, int col, int *matchcount, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find all files that match the description
|
// find all files that match the description
|
||||||
if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL) {
|
if (ExpandFromContext(xp, file_str, matches, matchcount, options) == FAIL) {
|
||||||
*matchcount = 0;
|
*matchcount = 0;
|
||||||
*matches = NULL;
|
*matches = NULL;
|
||||||
}
|
}
|
||||||
@@ -2209,8 +2243,8 @@ int expand_cmdline(expand_T *xp, const char *str, int col, int *matchcount, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Expand file or directory names.
|
/// Expand file or directory names.
|
||||||
static int expand_files_and_dirs(expand_T *xp, char *pat, char ***file, int *num_file, int flags,
|
static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int *numMatches,
|
||||||
int options)
|
int flags, int options)
|
||||||
{
|
{
|
||||||
bool free_pat = false;
|
bool free_pat = false;
|
||||||
|
|
||||||
@@ -2246,14 +2280,14 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***file, int *num
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Expand wildcards, supporting %:h and the like.
|
// Expand wildcards, supporting %:h and the like.
|
||||||
int ret = expand_wildcards_eval(&pat, num_file, file, flags);
|
int ret = expand_wildcards_eval(&pat, numMatches, matches, flags);
|
||||||
if (free_pat) {
|
if (free_pat) {
|
||||||
xfree(pat);
|
xfree(pat);
|
||||||
}
|
}
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) {
|
if (p_csl[0] != NUL && (options & WILD_IGNORE_COMPLETESLASH) == 0) {
|
||||||
for (int j = 0; j < *num_file; j++) {
|
for (int j = 0; j < *numMatches; j++) {
|
||||||
char *ptr = (*file)[j];
|
char *ptr = (*matches)[j];
|
||||||
while (*ptr != NUL) {
|
while (*ptr != NUL) {
|
||||||
if (p_csl[0] == 's' && *ptr == '\\') {
|
if (p_csl[0] == 's' && *ptr == '\\') {
|
||||||
*ptr = '/';
|
*ptr = '/';
|
||||||
@@ -2326,7 +2360,7 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Do the expansion based on xp->xp_context and "rmp".
|
/// Do the expansion based on xp->xp_context and "rmp".
|
||||||
static int ExpandOther(expand_T *xp, regmatch_T *rmp, int *num_file, char ***file)
|
static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
|
||||||
{
|
{
|
||||||
typedef CompleteListItemGetter ExpandFunc;
|
typedef CompleteListItemGetter ExpandFunc;
|
||||||
static struct expgen {
|
static struct expgen {
|
||||||
@@ -2376,7 +2410,7 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, int *num_file, char ***fil
|
|||||||
if (tab[i].ic) {
|
if (tab[i].ic) {
|
||||||
rmp->rm_ic = true;
|
rmp->rm_ic = true;
|
||||||
}
|
}
|
||||||
ExpandGeneric(xp, rmp, num_file, file, tab[i].func, tab[i].escaped);
|
ExpandGeneric(xp, rmp, matches, numMatches, tab[i].func, tab[i].escaped);
|
||||||
ret = OK;
|
ret = OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2414,7 +2448,7 @@ static int map_wildopts_to_ewflags(int options)
|
|||||||
/// Do the expansion based on xp->xp_context and "pat".
|
/// Do the expansion based on xp->xp_context and "pat".
|
||||||
///
|
///
|
||||||
/// @param options WILD_ flags
|
/// @param options WILD_ flags
|
||||||
static int ExpandFromContext(expand_T *xp, char *pat, int *num_file, char ***file, int options)
|
static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numMatches, int options)
|
||||||
{
|
{
|
||||||
regmatch_T regmatch;
|
regmatch_T regmatch;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -2423,65 +2457,64 @@ static int ExpandFromContext(expand_T *xp, char *pat, int *num_file, char ***fil
|
|||||||
if (xp->xp_context == EXPAND_FILES
|
if (xp->xp_context == EXPAND_FILES
|
||||||
|| xp->xp_context == EXPAND_DIRECTORIES
|
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||||
|| xp->xp_context == EXPAND_FILES_IN_PATH) {
|
|| xp->xp_context == EXPAND_FILES_IN_PATH) {
|
||||||
return expand_files_and_dirs(xp, pat, file, num_file, flags, options);
|
return expand_files_and_dirs(xp, pat, matches, numMatches, flags, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
*file = NULL;
|
*matches = NULL;
|
||||||
*num_file = 0;
|
*numMatches = 0;
|
||||||
if (xp->xp_context == EXPAND_HELP) {
|
if (xp->xp_context == EXPAND_HELP) {
|
||||||
// With an empty argument we would get all the help tags, which is
|
// With an empty argument we would get all the help tags, which is
|
||||||
// very slow. Get matches for "help" instead.
|
// very slow. Get matches for "help" instead.
|
||||||
if (find_help_tags(*pat == NUL ? "help" : pat,
|
if (find_help_tags(*pat == NUL ? "help" : pat,
|
||||||
num_file, file, false) == OK) {
|
numMatches, matches, false) == OK) {
|
||||||
cleanup_help_tags(*num_file, *file);
|
cleanup_help_tags(*numMatches, *matches);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xp->xp_context == EXPAND_SHELLCMD) {
|
if (xp->xp_context == EXPAND_SHELLCMD) {
|
||||||
*file = NULL;
|
expand_shellcmd(pat, matches, numMatches, flags);
|
||||||
expand_shellcmd(pat, num_file, file, flags);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_OLD_SETTING) {
|
if (xp->xp_context == EXPAND_OLD_SETTING) {
|
||||||
ExpandOldSetting(num_file, file);
|
ExpandOldSetting(numMatches, matches);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_BUFFERS) {
|
if (xp->xp_context == EXPAND_BUFFERS) {
|
||||||
return ExpandBufnames(pat, num_file, file, options);
|
return ExpandBufnames(pat, numMatches, matches, options);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_DIFF_BUFFERS) {
|
if (xp->xp_context == EXPAND_DIFF_BUFFERS) {
|
||||||
return ExpandBufnames(pat, num_file, file, options | BUF_DIFF_FILTER);
|
return ExpandBufnames(pat, numMatches, matches, options | BUF_DIFF_FILTER);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_TAGS
|
if (xp->xp_context == EXPAND_TAGS
|
||||||
|| xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
|| xp->xp_context == EXPAND_TAGS_LISTFILES) {
|
||||||
return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file);
|
return expand_tags(xp->xp_context == EXPAND_TAGS, pat, numMatches, matches);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_COLORS) {
|
if (xp->xp_context == EXPAND_COLORS) {
|
||||||
char *directories[] = { "colors", NULL };
|
char *directories[] = { "colors", NULL };
|
||||||
return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_LUA, num_file, file, directories);
|
return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_LUA, numMatches, matches, directories);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_COMPILER) {
|
if (xp->xp_context == EXPAND_COMPILER) {
|
||||||
char *directories[] = { "compiler", NULL };
|
char *directories[] = { "compiler", NULL };
|
||||||
return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
|
return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_OWNSYNTAX) {
|
if (xp->xp_context == EXPAND_OWNSYNTAX) {
|
||||||
char *directories[] = { "syntax", NULL };
|
char *directories[] = { "syntax", NULL };
|
||||||
return ExpandRTDir(pat, 0, num_file, file, directories);
|
return ExpandRTDir(pat, 0, numMatches, matches, directories);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_FILETYPE) {
|
if (xp->xp_context == EXPAND_FILETYPE) {
|
||||||
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
|
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
|
||||||
return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
|
return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_USER_LIST) {
|
if (xp->xp_context == EXPAND_USER_LIST) {
|
||||||
return ExpandUserList(xp, num_file, file);
|
return ExpandUserList(xp, matches, numMatches);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_USER_LUA) {
|
if (xp->xp_context == EXPAND_USER_LUA) {
|
||||||
return ExpandUserLua(xp, num_file, file);
|
return ExpandUserLua(xp, numMatches, matches);
|
||||||
}
|
}
|
||||||
if (xp->xp_context == EXPAND_PACKADD) {
|
if (xp->xp_context == EXPAND_PACKADD) {
|
||||||
return ExpandPackAddDir(pat, num_file, file);
|
return ExpandPackAddDir(pat, numMatches, matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When expanding a function name starting with s:, match the <SNR>nr_
|
// When expanding a function name starting with s:, match the <SNR>nr_
|
||||||
@@ -2497,7 +2530,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, int *num_file, char ***fil
|
|||||||
|
|
||||||
if (xp->xp_context == EXPAND_LUA) {
|
if (xp->xp_context == EXPAND_LUA) {
|
||||||
ILOG("PAT %s", pat);
|
ILOG("PAT %s", pat);
|
||||||
return nlua_expand_pat(xp, pat, num_file, file);
|
return nlua_expand_pat(xp, pat, numMatches, matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
|
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
|
||||||
@@ -2510,13 +2543,13 @@ static int ExpandFromContext(expand_T *xp, char *pat, int *num_file, char ***fil
|
|||||||
|
|
||||||
if (xp->xp_context == EXPAND_SETTINGS
|
if (xp->xp_context == EXPAND_SETTINGS
|
||||||
|| xp->xp_context == EXPAND_BOOL_SETTINGS) {
|
|| xp->xp_context == EXPAND_BOOL_SETTINGS) {
|
||||||
ret = ExpandSettings(xp, ®match, num_file, file);
|
ret = ExpandSettings(xp, ®match, numMatches, matches);
|
||||||
} else if (xp->xp_context == EXPAND_MAPPINGS) {
|
} else if (xp->xp_context == EXPAND_MAPPINGS) {
|
||||||
ret = ExpandMappings(®match, num_file, file);
|
ret = ExpandMappings(®match, numMatches, matches);
|
||||||
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
|
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
|
||||||
ret = ExpandUserDefined(xp, ®match, num_file, file);
|
ret = ExpandUserDefined(xp, ®match, matches, numMatches);
|
||||||
} else {
|
} else {
|
||||||
ret = ExpandOther(xp, ®match, num_file, file);
|
ret = ExpandOther(xp, ®match, matches, numMatches);
|
||||||
}
|
}
|
||||||
|
|
||||||
vim_regfree(regmatch.regprog);
|
vim_regfree(regmatch.regprog);
|
||||||
@@ -2532,7 +2565,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, int *num_file, char ***fil
|
|||||||
/// program. Matching strings are copied into an array, which is returned.
|
/// program. Matching strings are copied into an array, which is returned.
|
||||||
///
|
///
|
||||||
/// @param func returns a string from the list
|
/// @param func returns a string from the list
|
||||||
static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file,
|
static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches,
|
||||||
CompleteListItemGetter func, int escaped)
|
CompleteListItemGetter func, int escaped)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -2556,8 +2589,8 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(count < INT_MAX);
|
assert(count < INT_MAX);
|
||||||
*num_file = (int)count;
|
*numMatches = (int)count;
|
||||||
*file = xmalloc(count * sizeof(char *));
|
*matches = xmalloc(count * sizeof(char *));
|
||||||
|
|
||||||
// copy the matching names into allocated memory
|
// copy the matching names into allocated memory
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -2575,7 +2608,7 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
|
|||||||
} else {
|
} else {
|
||||||
str = xstrdup(str);
|
str = xstrdup(str);
|
||||||
}
|
}
|
||||||
(*file)[count++] = str;
|
(*matches)[count++] = str;
|
||||||
if (func == get_menu_names) {
|
if (func == get_menu_names) {
|
||||||
// Test for separator added by get_menu_names().
|
// Test for separator added by get_menu_names().
|
||||||
str += strlen(str) - 1;
|
str += strlen(str) - 1;
|
||||||
@@ -2592,9 +2625,9 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
|
|||||||
|| xp->xp_context == EXPAND_FUNCTIONS
|
|| xp->xp_context == EXPAND_FUNCTIONS
|
||||||
|| xp->xp_context == EXPAND_USER_FUNC) {
|
|| xp->xp_context == EXPAND_USER_FUNC) {
|
||||||
// <SNR> functions should be sorted to the end.
|
// <SNR> functions should be sorted to the end.
|
||||||
qsort((void *)(*file), (size_t)(*num_file), sizeof(char *), sort_func_compare);
|
qsort((void *)(*matches), (size_t)(*numMatches), sizeof(char *), sort_func_compare);
|
||||||
} else {
|
} else {
|
||||||
sort_strings(*file, *num_file);
|
sort_strings(*matches, *numMatches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2604,8 +2637,8 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Expand shell command matches in one directory of $PATH.
|
/// Expand shell command matches in one directory of $PATH.
|
||||||
static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char ***files,
|
static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char ***matches,
|
||||||
int *num_files, int flags, hashtab_T *ht, garray_T *gap)
|
int *numMatches, int flags, hashtab_T *ht, garray_T *gap)
|
||||||
{
|
{
|
||||||
xstrlcpy(buf, s, l + 1);
|
xstrlcpy(buf, s, l + 1);
|
||||||
add_pathsep(buf);
|
add_pathsep(buf);
|
||||||
@@ -2613,12 +2646,12 @@ static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char
|
|||||||
xstrlcpy(buf + l, pat, MAXPATHL - l);
|
xstrlcpy(buf + l, pat, MAXPATHL - l);
|
||||||
|
|
||||||
// Expand matches in one directory of $PATH.
|
// Expand matches in one directory of $PATH.
|
||||||
int ret = expand_wildcards(1, &buf, num_files, files, flags);
|
int ret = expand_wildcards(1, &buf, numMatches, matches, flags);
|
||||||
if (ret == OK) {
|
if (ret == OK) {
|
||||||
ga_grow(gap, *num_files);
|
ga_grow(gap, *numMatches);
|
||||||
{
|
{
|
||||||
for (int i = 0; i < *num_files; i++) {
|
for (int i = 0; i < *numMatches; i++) {
|
||||||
char *name = (*files)[i];
|
char *name = (*matches)[i];
|
||||||
|
|
||||||
if (strlen(name) > l) {
|
if (strlen(name) > l) {
|
||||||
// Check if this name was already found.
|
// Check if this name was already found.
|
||||||
@@ -2635,7 +2668,7 @@ static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char
|
|||||||
}
|
}
|
||||||
xfree(name);
|
xfree(name);
|
||||||
}
|
}
|
||||||
xfree(*files);
|
xfree(*matches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2643,12 +2676,12 @@ static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char
|
|||||||
/// Complete a shell command.
|
/// Complete a shell command.
|
||||||
///
|
///
|
||||||
/// @param filepat is a pattern to match with command names.
|
/// @param filepat is a pattern to match with command names.
|
||||||
/// @param[out] num_file is pointer to number of matches.
|
/// @param[out] matches is pointer to array of pointers to matches.
|
||||||
/// @param[out] file is pointer to array of pointers to matches.
|
/// *matches will either be set to NULL or point to
|
||||||
/// *file will either be set to NULL or point to
|
|
||||||
/// allocated memory.
|
/// allocated memory.
|
||||||
|
/// @param[out] numMatches is pointer to number of matches.
|
||||||
/// @param flagsarg is a combination of EW_* flags.
|
/// @param flagsarg is a combination of EW_* flags.
|
||||||
static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flagsarg)
|
static void expand_shellcmd(char *filepat, char ***matches, int *numMatches, int flagsarg)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
char *pat;
|
char *pat;
|
||||||
@@ -2718,13 +2751,13 @@ static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flag
|
|||||||
if (l > MAXPATHL - 5) {
|
if (l > MAXPATHL - 5) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
expand_shellcmd_onedir(buf, s, l, pat, file, num_file, flags, &found_ht, &ga);
|
expand_shellcmd_onedir(buf, s, l, pat, matches, numMatches, flags, &found_ht, &ga);
|
||||||
if (*e != NUL) {
|
if (*e != NUL) {
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*file = ga.ga_data;
|
*matches = ga.ga_data;
|
||||||
*num_file = ga.ga_len;
|
*numMatches = ga.ga_len;
|
||||||
|
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
xfree(pat);
|
xfree(pat);
|
||||||
@@ -2736,8 +2769,7 @@ static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flag
|
|||||||
|
|
||||||
/// Call "user_expand_func()" to invoke a user defined Vim script function and
|
/// Call "user_expand_func()" to invoke a user defined Vim script function and
|
||||||
/// return the result (either a string, a List or NULL).
|
/// return the result (either a string, a List or NULL).
|
||||||
static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file,
|
static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp)
|
||||||
char ***file)
|
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
CmdlineInfo *const ccline = get_cmdline_info();
|
CmdlineInfo *const ccline = get_cmdline_info();
|
||||||
@@ -2749,8 +2781,6 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
|
|||||||
if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) {
|
if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*num_file = 0;
|
|
||||||
*file = NULL;
|
|
||||||
|
|
||||||
if (ccline->cmdbuff != NULL) {
|
if (ccline->cmdbuff != NULL) {
|
||||||
keep = ccline->cmdbuff[ccline->cmdlen];
|
keep = ccline->cmdbuff[ccline->cmdlen];
|
||||||
@@ -2780,13 +2810,14 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Expand names with a function defined by the user.
|
/// Expand names with a function defined by the user.
|
||||||
static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file)
|
static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches)
|
||||||
{
|
{
|
||||||
char *e;
|
char *e;
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
|
|
||||||
char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, num_file,
|
*matches = NULL;
|
||||||
file);
|
*numMatches = 0;
|
||||||
|
char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp);
|
||||||
|
|
||||||
if (retstr == NULL) {
|
if (retstr == NULL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -2812,16 +2843,17 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree(retstr);
|
xfree(retstr);
|
||||||
*file = ga.ga_data;
|
*matches = ga.ga_data;
|
||||||
*num_file = ga.ga_len;
|
*numMatches = ga.ga_len;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand names with a list returned by a function defined by the user.
|
/// Expand names with a list returned by a function defined by the user.
|
||||||
static int ExpandUserList(expand_T *xp, int *num_file, char ***file)
|
static int ExpandUserList(expand_T *xp, char ***matches, int *numMatches)
|
||||||
{
|
{
|
||||||
list_T *const retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp, num_file,
|
*matches = NULL;
|
||||||
file);
|
*numMatches = 0;
|
||||||
|
list_T *const retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp);
|
||||||
if (retlist == NULL) {
|
if (retlist == NULL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@@ -2839,8 +2871,8 @@ static int ExpandUserList(expand_T *xp, int *num_file, char ***file)
|
|||||||
});
|
});
|
||||||
tv_list_unref(retlist);
|
tv_list_unref(retlist);
|
||||||
|
|
||||||
*file = ga.ga_data;
|
*matches = ga.ga_data;
|
||||||
*num_file = ga.ga_len;
|
*numMatches = ga.ga_len;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2893,7 +2925,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options)
|
|||||||
|
|
||||||
char **p;
|
char **p;
|
||||||
int num_p = 0;
|
int num_p = 0;
|
||||||
(void)ExpandFromContext(&xpc, buf, &num_p, &p,
|
(void)ExpandFromContext(&xpc, buf, &p, &num_p,
|
||||||
WILD_SILENT | expand_options);
|
WILD_SILENT | expand_options);
|
||||||
if (num_p > 0) {
|
if (num_p > 0) {
|
||||||
ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT | expand_options);
|
ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT | expand_options);
|
||||||
|
@@ -354,6 +354,14 @@ func Test_CmdCompletion()
|
|||||||
call feedkeys(":com -complete=co\<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":com -complete=co\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"com -complete=color command compiler', @:)
|
call assert_equal('"com -complete=color command compiler', @:)
|
||||||
|
|
||||||
|
" try completion for unsupported argument values
|
||||||
|
call feedkeys(":com -newarg=\<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"com -newarg=\t", @:)
|
||||||
|
|
||||||
|
" command completion after the name in a user defined command
|
||||||
|
call feedkeys(":com MyCmd chist\<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"com MyCmd chistory", @:)
|
||||||
|
|
||||||
command! DoCmd1 :
|
command! DoCmd1 :
|
||||||
command! DoCmd2 :
|
command! DoCmd2 :
|
||||||
call feedkeys(":com \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":com \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
@@ -365,6 +373,10 @@ func Test_CmdCompletion()
|
|||||||
call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"delcom DoCmd1 DoCmd2', @:)
|
call assert_equal('"delcom DoCmd1 DoCmd2', @:)
|
||||||
|
|
||||||
|
" try argument completion for a command without completion
|
||||||
|
call feedkeys(":DoCmd1 \<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"DoCmd1 \t", @:)
|
||||||
|
|
||||||
delcom DoCmd1
|
delcom DoCmd1
|
||||||
call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"delcom DoCmd2', @:)
|
call assert_equal('"delcom DoCmd2', @:)
|
||||||
@@ -383,6 +395,21 @@ func Test_CmdCompletion()
|
|||||||
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"DoCmd mswin xterm', @:)
|
call assert_equal('"DoCmd mswin xterm', @:)
|
||||||
|
|
||||||
|
" Test for file name completion
|
||||||
|
com! -nargs=1 -complete=file DoCmd :
|
||||||
|
call feedkeys(":DoCmd READM\<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"DoCmd README.txt', @:)
|
||||||
|
|
||||||
|
" Test for buffer name completion
|
||||||
|
com! -nargs=1 -complete=buffer DoCmd :
|
||||||
|
let bnum = bufadd('BufForUserCmd')
|
||||||
|
call setbufvar(bnum, '&buflisted', 1)
|
||||||
|
call feedkeys(":DoCmd BufFor\<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"DoCmd BufForUserCmd', @:)
|
||||||
|
bwipe BufForUserCmd
|
||||||
|
call feedkeys(":DoCmd BufFor\<Tab>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"DoCmd BufFor', @:)
|
||||||
|
|
||||||
com! -nargs=* -complete=custom,CustomComplete DoCmd :
|
com! -nargs=* -complete=custom,CustomComplete DoCmd :
|
||||||
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"DoCmd January February Mars', @:)
|
call assert_equal('"DoCmd January February Mars', @:)
|
||||||
@@ -694,5 +721,30 @@ func Test_recursive_define()
|
|||||||
endwhile
|
endwhile
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for using buffer-local ambiguous user-defined commands
|
||||||
|
func Test_buflocal_ambiguous_usercmd()
|
||||||
|
new
|
||||||
|
command -buffer -nargs=1 -complete=sign TestCmd1 echo "Hello"
|
||||||
|
command -buffer -nargs=1 -complete=sign TestCmd2 echo "World"
|
||||||
|
|
||||||
|
call assert_fails("call feedkeys(':TestCmd\<CR>', 'xt')", 'E464:')
|
||||||
|
call feedkeys(":TestCmd \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal('"TestCmd ', @:)
|
||||||
|
|
||||||
|
delcommand TestCmd1
|
||||||
|
delcommand TestCmd2
|
||||||
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for using a multibyte character in a user command
|
||||||
|
func Test_multibyte_in_usercmd()
|
||||||
|
command SubJapanesePeriodToDot exe "%s/\u3002/./g"
|
||||||
|
new
|
||||||
|
call setline(1, "Hello\u3002")
|
||||||
|
SubJapanesePeriodToDot
|
||||||
|
call assert_equal('Hello.', getline(1))
|
||||||
|
bw!
|
||||||
|
delcommand SubJapanesePeriodToDot
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user