1
0
forked from aniani/vim

updated for version 7.4.279

Problem:    globpath() returns a string, making it difficult to get a list of
            matches. (Greg Novack)
Solution:   Add an optional argument like with glob(). (Adnan Zafar)
This commit is contained in:
Bram Moolenaar
2014-05-07 18:35:30 +02:00
parent 3ec7f4e402
commit 1b1063af58
10 changed files with 100 additions and 101 deletions

View File

@@ -1832,7 +1832,7 @@ getwinvar( {nr}, {varname} [, {def}])
any variable {varname} in window {nr} any variable {varname} in window {nr}
glob( {expr} [, {nosuf} [, {list}]]) glob( {expr} [, {nosuf} [, {list}]])
any expand file wildcards in {expr} any expand file wildcards in {expr}
globpath( {path}, {expr} [, {flag}]) globpath( {path}, {expr} [, {nosuf} [, {list}]])
String do glob({expr}) for all dirs in {path} String do glob({expr}) for all dirs in {path}
has( {feature}) Number TRUE if feature {feature} supported has( {feature}) Number TRUE if feature {feature} supported
has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} has_key( {dict}, {key}) Number TRUE if {dict} has entry {key}
@@ -3571,11 +3571,12 @@ glob({expr} [, {nosuf} [, {list}]]) *glob()*
See |expand()| for expanding special Vim variables. See See |expand()| for expanding special Vim variables. See
|system()| for getting the raw output of an external command. |system()| for getting the raw output of an external command.
globpath({path}, {expr} [, {flag}]) *globpath()* globpath({path}, {expr} [, {nosuf} [, {list}]]) *globpath()*
Perform glob() on all directories in {path} and concatenate Perform glob() on all directories in {path} and concatenate
the results. Example: > the results. Example: >
:echo globpath(&rtp, "syntax/c.vim") :echo globpath(&rtp, "syntax/c.vim")
< {path} is a comma-separated list of directory names. Each <
{path} is a comma-separated list of directory names. Each
directory name is prepended to {expr} and expanded like with directory name is prepended to {expr} and expanded like with
|glob()|. A path separator is inserted when needed. |glob()|. A path separator is inserted when needed.
To add a comma inside a directory name escape it with a To add a comma inside a directory name escape it with a
@@ -3583,11 +3584,19 @@ globpath({path}, {expr} [, {flag}]) *globpath()*
trailing backslash, remove it if you put a comma after it. trailing backslash, remove it if you put a comma after it.
If the expansion fails for one of the directories, there is no If the expansion fails for one of the directories, there is no
error message. error message.
Unless the optional {flag} argument is given and is non-zero,
Unless the optional {nosuf} argument is given and is non-zero,
the 'suffixes' and 'wildignore' options apply: Names matching the 'suffixes' and 'wildignore' options apply: Names matching
one of the patterns in 'wildignore' will be skipped and one of the patterns in 'wildignore' will be skipped and
'suffixes' affect the ordering of matches. 'suffixes' affect the ordering of matches.
When {list} is present and it is non-zero the result is a List
with all matching files. The advantage of using a List is, you
also get filenames containing newlines correctly. Otherwise
the result is a String and when there are several matches,
they are separated by <NL> characters. Example: >
:echo globpath(&rtp, "syntax/c.vim", 0, 1)
<
The "**" item can be used to search in a directory tree. The "**" item can be used to search in a directory tree.
For example, to find all "README.txt" files in the directories For example, to find all "README.txt" files in the directories
in 'runtimepath' and below: > in 'runtimepath' and below: >

View File

@@ -7985,7 +7985,7 @@ static struct fst
{"getwinposy", 0, 0, f_getwinposy}, {"getwinposy", 0, 0, f_getwinposy},
{"getwinvar", 2, 3, f_getwinvar}, {"getwinvar", 2, 3, f_getwinvar},
{"glob", 1, 3, f_glob}, {"glob", 1, 3, f_glob},
{"globpath", 2, 3, f_globpath}, {"globpath", 2, 4, f_globpath},
{"has", 1, 1, f_has}, {"has", 1, 1, f_has},
{"has_key", 2, 2, f_has_key}, {"has_key", 2, 2, f_has_key},
{"haslocaldir", 0, 0, f_haslocaldir}, {"haslocaldir", 0, 0, f_haslocaldir},
@@ -12151,18 +12151,37 @@ f_globpath(argvars, rettv)
char_u buf1[NUMBUFLEN]; char_u buf1[NUMBUFLEN];
char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
int error = FALSE; int error = FALSE;
garray_T ga;
int i;
/* When the optional second argument is non-zero, don't remove matches /* When the optional second argument is non-zero, don't remove matches
* for 'wildignore' and don't put matches for 'suffixes' at the end. */ * for 'wildignore' and don't put matches for 'suffixes' at the end. */
if (argvars[2].v_type != VAR_UNKNOWN
&& get_tv_number_chk(&argvars[2], &error))
flags |= WILD_KEEP_ALL;
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
if (file == NULL || error) if (argvars[2].v_type != VAR_UNKNOWN)
rettv->vval.v_string = NULL; {
if (get_tv_number_chk(&argvars[2], &error))
flags |= WILD_KEEP_ALL;
if (argvars[3].v_type != VAR_UNKNOWN
&& get_tv_number_chk(&argvars[3], &error))
{
rettv->v_type = VAR_LIST;
rettv->vval.v_list = NULL;
}
}
if (file != NULL && !error)
{
ga_init2(&ga, (int)sizeof(char_u *), 10);
globpath(get_tv_string(&argvars[0]), file, &ga, flags);
if (rettv->v_type == VAR_STRING)
rettv->vval.v_string = ga_concat_strings(&ga, "\n");
else if (rettv_list_alloc(rettv) != FAIL)
for (i = 0; i < ga.ga_len; ++i)
list_append_string(rettv->vval.v_list,
((char_u **)(ga.ga_data))[i], -1);
ga_clear_strings(&ga);
}
else else
rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file, rettv->vval.v_string = NULL;
flags);
} }
/* /*

View File

@@ -5095,9 +5095,9 @@ ExpandRTDir(pat, num_file, file, dirnames)
char_u ***file; char_u ***file;
char *dirnames[]; char *dirnames[];
{ {
char_u *matches;
char_u *s; char_u *s;
char_u *e; char_u *e;
char_u *match;
garray_T ga; garray_T ga;
int i; int i;
int pat_len; int pat_len;
@@ -5116,33 +5116,27 @@ ExpandRTDir(pat, num_file, file, dirnames)
return FAIL; return FAIL;
} }
sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat);
matches = globpath(p_rtp, s, 0); globpath(p_rtp, s, &ga, 0);
vim_free(s); vim_free(s);
if (matches == NULL) }
continue;
for (s = matches; *s != NUL; s = e) for (i = 0; i < ga.ga_len; ++i)
{ {
e = vim_strchr(s, '\n'); match = ((char_u **)ga.ga_data)[i];
if (e == NULL) s = match;
e = s + STRLEN(s); e = s + STRLEN(s);
if (ga_grow(&ga, 1) == FAIL)
break;
if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0)
{ {
for (s = e - 4; s > matches; mb_ptr_back(matches, s)) e -= 4;
if (*s == '\n' || vim_ispathsep(*s)) for (s = e; s > match; mb_ptr_back(match, s))
if (s < match || vim_ispathsep(*s))
break; break;
++s; ++s;
((char_u **)ga.ga_data)[ga.ga_len] = *e = NUL;
vim_strnsave(s, (int)(e - s - 4)); mch_memmove(match, s, e - s + 1);
++ga.ga_len;
} }
if (*e != NUL)
++e;
}
vim_free(matches);
} }
if (ga.ga_len == 0) if (ga.ga_len == 0)
return FAIL; return FAIL;
@@ -5160,33 +5154,28 @@ ExpandRTDir(pat, num_file, file, dirnames)
#if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO) #if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO)
/* /*
* Expand "file" for all comma-separated directories in "path". * Expand "file" for all comma-separated directories in "path".
* Returns an allocated string with all matches concatenated, separated by * Adds the matches to "ga". Caller must init "ga".
* newlines. Returns NULL for an error or no matches.
*/ */
char_u * void
globpath(path, file, expand_options) globpath(path, file, ga, expand_options)
char_u *path; char_u *path;
char_u *file; char_u *file;
garray_T *ga;
int expand_options; int expand_options;
{ {
expand_T xpc; expand_T xpc;
char_u *buf; char_u *buf;
garray_T ga;
int i; int i;
int len;
int num_p; int num_p;
char_u **p; char_u **p;
char_u *cur = NULL;
buf = alloc(MAXPATHL); buf = alloc(MAXPATHL);
if (buf == NULL) if (buf == NULL)
return NULL; return;
ExpandInit(&xpc); ExpandInit(&xpc);
xpc.xp_context = EXPAND_FILES; xpc.xp_context = EXPAND_FILES;
ga_init2(&ga, 1, 100);
/* Loop over all entries in {path}. */ /* Loop over all entries in {path}. */
while (*path != NUL) while (*path != NUL)
{ {
@@ -5207,30 +5196,23 @@ globpath(path, file, expand_options)
WILD_SILENT|expand_options) != FAIL && num_p > 0) WILD_SILENT|expand_options) != FAIL && num_p > 0)
{ {
ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options);
for (len = 0, i = 0; i < num_p; ++i)
len += (int)STRLEN(p[i]) + 1;
/* Concatenate new results to previous ones. */ if (ga_grow(ga, num_p) == OK)
if (ga_grow(&ga, len) == OK)
{ {
cur = (char_u *)ga.ga_data + ga.ga_len;
for (i = 0; i < num_p; ++i) for (i = 0; i < num_p; ++i)
{ {
STRCPY(cur, p[i]); ((char_u **)ga->ga_data)[ga->ga_len] =
cur += STRLEN(p[i]); vim_strnsave(p[i], STRLEN(p[i]));
*cur++ = '\n'; ++ga->ga_len;
} }
ga.ga_len += len;
} }
FreeWild(num_p, p); FreeWild(num_p, p);
} }
} }
} }
if (cur != NULL)
*--cur = 0; /* Replace trailing newline with NUL */
vim_free(buf); vim_free(buf);
return (char_u *)ga.ga_data;
} }
#endif #endif

View File

@@ -10336,9 +10336,6 @@ expand_in_path(gap, pattern, flags)
{ {
char_u *curdir; char_u *curdir;
garray_T path_ga; garray_T path_ga;
char_u *files = NULL;
char_u *s; /* start */
char_u *e; /* end */
char_u *paths = NULL; char_u *paths = NULL;
if ((curdir = alloc((unsigned)MAXPATHL)) == NULL) if ((curdir = alloc((unsigned)MAXPATHL)) == NULL)
@@ -10351,37 +10348,13 @@ expand_in_path(gap, pattern, flags)
if (path_ga.ga_len == 0) if (path_ga.ga_len == 0)
return 0; return 0;
paths = ga_concat_strings(&path_ga); paths = ga_concat_strings(&path_ga, ",");
ga_clear_strings(&path_ga); ga_clear_strings(&path_ga);
if (paths == NULL) if (paths == NULL)
return 0; return 0;
files = globpath(paths, pattern, (flags & EW_ICASE) ? WILD_ICASE : 0); globpath(paths, pattern, gap, (flags & EW_ICASE) ? WILD_ICASE : 0);
vim_free(paths); vim_free(paths);
if (files == NULL)
return 0;
/* Copy each path in files into gap */
s = e = files;
while (*s != NUL)
{
while (*e != '\n' && *e != NUL)
e++;
if (*e == NUL)
{
addfile(gap, s, flags);
break;
}
else
{
/* *e is '\n' */
*e = NUL;
addfile(gap, s, flags);
e++;
s = e;
}
}
vim_free(files);
return gap->ga_len; return gap->ga_len;
} }

View File

@@ -2087,29 +2087,37 @@ ga_grow(gap, n)
/* /*
* For a growing array that contains a list of strings: concatenate all the * For a growing array that contains a list of strings: concatenate all the
* strings with a separating comma. * strings with a separating "sep".
* Returns NULL when out of memory. * Returns NULL when out of memory.
*/ */
char_u * char_u *
ga_concat_strings(gap) ga_concat_strings(gap, sep)
garray_T *gap; garray_T *gap;
char *sep;
{ {
int i; int i;
int len = 0; int len = 0;
int sep_len = (int)STRLEN(sep);
char_u *s; char_u *s;
char_u *p;
for (i = 0; i < gap->ga_len; ++i) for (i = 0; i < gap->ga_len; ++i)
len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + 1; len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len;
s = alloc(len + 1); s = alloc(len + 1);
if (s != NULL) if (s != NULL)
{ {
*s = NUL; *s = NUL;
p = s;
for (i = 0; i < gap->ga_len; ++i) for (i = 0; i < gap->ga_len; ++i)
{ {
if (*s != NUL) if (p != s)
STRCAT(s, ","); {
STRCAT(s, ((char_u **)(gap->ga_data))[i]); STRCPY(p, sep);
p += sep_len;
}
STRCPY(p, ((char_u **)(gap->ga_data))[i]);
p += STRLEN(p);
} }
} }
return s; return s;

View File

@@ -32,7 +32,7 @@ char_u *addstar __ARGS((char_u *fname, int len, int context));
void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col)); void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col));
int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches)); int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches));
int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped)); int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped));
char_u *globpath __ARGS((char_u *path, char_u *file, int expand_options)); void globpath __ARGS((char_u *path, char_u *file, garray_T *ga, int expand_options));
void init_history __ARGS((void)); void init_history __ARGS((void));
int get_histtype __ARGS((char_u *name)); int get_histtype __ARGS((char_u *name));
void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep)); void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep));

View File

@@ -55,7 +55,7 @@ void ga_clear_strings __ARGS((garray_T *gap));
void ga_init __ARGS((garray_T *gap)); void ga_init __ARGS((garray_T *gap));
void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize)); void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize));
int ga_grow __ARGS((garray_T *gap, int n)); int ga_grow __ARGS((garray_T *gap, int n));
char_u *ga_concat_strings __ARGS((garray_T *gap)); char_u *ga_concat_strings __ARGS((garray_T *gap, char *sep));
void ga_concat __ARGS((garray_T *gap, char_u *s)); void ga_concat __ARGS((garray_T *gap, char_u *s));
void ga_append __ARGS((garray_T *gap, int c)); void ga_append __ARGS((garray_T *gap, int c));
void append_ga_line __ARGS((garray_T *gap)); void append_ga_line __ARGS((garray_T *gap));

View File

@@ -5,12 +5,15 @@ STARTTEST
:so small.vim :so small.vim
:set shell=doesnotexist :set shell=doesnotexist
:e test.out :e test.out
:put =glob('Xxx\{') :$put =glob('Xxx\{')
:put =glob('Xxx\$') :$put =glob('Xxx\$')
:w! Xxx{ :w! Xxx{
:w! Xxx\$ :w! Xxx\$
:put =glob('Xxx\{') :$put =glob('Xxx\{')
:put =glob('Xxx\$') :$put =glob('Xxx\$')
:"
:$put =string(globpath('sautest/autoload', '*.vim'))
:$put =string(globpath('sautest/autoload', '*.vim', 0, 1))
:w :w
:qa! :qa!
ENDTEST ENDTEST

View File

@@ -3,3 +3,6 @@
Xxx{ Xxx{
Xxx$ Xxx$
'sautest/autoload/Test104.vim
sautest/autoload/footest.vim'
['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim']

View File

@@ -734,6 +734,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 */
/**/
279,
/**/ /**/
278, 278,
/**/ /**/