| To: vim_dev@googlegroups.com |
| Subject: Patch 7.4.279 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 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) |
| Files: runtime/doc/eval.txt, src/eval.c, src/ex_getln.c, src/misc1.c, |
| src/misc2.c, src/proto/ex_getln.pro, src/proto/misc2.pro, |
| src/testdir/test97.in, src/testdir/test97.ok |
| |
| |
| |
| |
| |
| *** 1832,1838 **** |
| any variable {varname} in window {nr} |
| glob( {expr} [, {nosuf} [, {list}]]) |
| any expand file wildcards in {expr} |
| ! globpath( {path}, {expr} [, {flag}]) |
| String do glob({expr}) for all dirs in {path} |
| has( {feature}) Number TRUE if feature {feature} supported |
| has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} |
| --- 1832,1838 ---- |
| any variable {varname} in window {nr} |
| glob( {expr} [, {nosuf} [, {list}]]) |
| any expand file wildcards in {expr} |
| ! globpath( {path}, {expr} [, {nosuf} [, {list}]]) |
| String do glob({expr}) for all dirs in {path} |
| has( {feature}) Number TRUE if feature {feature} supported |
| has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} |
| |
| *** 3570,3580 **** |
| See |expand()| for expanding special Vim variables. See |
| |system()| for getting the raw output of an external command. |
| |
| ! globpath({path}, {expr} [, {flag}]) *globpath()* |
| Perform glob() on all directories in {path} and concatenate |
| the results. Example: > |
| :echo globpath(&rtp, "syntax/c.vim") |
| ! < {path} is a comma-separated list of directory names. Each |
| directory name is prepended to {expr} and expanded like with |
| |glob()|. A path separator is inserted when needed. |
| To add a comma inside a directory name escape it with a |
| --- 3571,3582 ---- |
| See |expand()| for expanding special Vim variables. See |
| |system()| for getting the raw output of an external command. |
| |
| ! globpath({path}, {expr} [, {nosuf} [, {list}]]) *globpath()* |
| Perform glob() on all directories in {path} and concatenate |
| the results. Example: > |
| :echo globpath(&rtp, "syntax/c.vim") |
| ! < |
| ! {path} is a comma-separated list of directory names. Each |
| directory name is prepended to {expr} and expanded like with |
| |glob()|. A path separator is inserted when needed. |
| To add a comma inside a directory name escape it with a |
| |
| *** 3582,3592 **** |
| trailing backslash, remove it if you put a comma after it. |
| If the expansion fails for one of the directories, there is no |
| error message. |
| ! Unless the optional {flag} argument is given and is non-zero, |
| the 'suffixes' and 'wildignore' options apply: Names matching |
| one of the patterns in 'wildignore' will be skipped and |
| 'suffixes' affect the ordering of matches. |
| |
| The "**" item can be used to search in a directory tree. |
| For example, to find all "README.txt" files in the directories |
| in 'runtimepath' and below: > |
| --- 3584,3602 ---- |
| trailing backslash, remove it if you put a comma after it. |
| If the expansion fails for one of the directories, there is no |
| error message. |
| ! |
| ! Unless the optional {nosuf} argument is given and is non-zero, |
| the 'suffixes' and 'wildignore' options apply: Names matching |
| one of the patterns in 'wildignore' will be skipped and |
| '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. |
| For example, to find all "README.txt" files in the directories |
| in 'runtimepath' and below: > |
| |
| |
| |
| *** 7985,7991 **** |
| {"getwinposy", 0, 0, f_getwinposy}, |
| {"getwinvar", 2, 3, f_getwinvar}, |
| {"glob", 1, 3, f_glob}, |
| ! {"globpath", 2, 3, f_globpath}, |
| {"has", 1, 1, f_has}, |
| {"has_key", 2, 2, f_has_key}, |
| {"haslocaldir", 0, 0, f_haslocaldir}, |
| --- 7985,7991 ---- |
| {"getwinposy", 0, 0, f_getwinposy}, |
| {"getwinvar", 2, 3, f_getwinvar}, |
| {"glob", 1, 3, f_glob}, |
| ! {"globpath", 2, 4, f_globpath}, |
| {"has", 1, 1, f_has}, |
| {"has_key", 2, 2, f_has_key}, |
| {"haslocaldir", 0, 0, f_haslocaldir}, |
| |
| *** 12151,12168 **** |
| char_u buf1[NUMBUFLEN]; |
| char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); |
| int error = FALSE; |
| |
| /* When the optional second argument is non-zero, don't remove matches |
| * 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; |
| ! if (file == NULL || error) |
| ! rettv->vval.v_string = NULL; |
| else |
| ! rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file, |
| ! flags); |
| } |
| |
| /* |
| --- 12151,12187 ---- |
| char_u buf1[NUMBUFLEN]; |
| char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); |
| int error = FALSE; |
| + garray_T ga; |
| + int i; |
| |
| /* When the optional second argument is non-zero, don't remove matches |
| * for 'wildignore' and don't put matches for 'suffixes' at the end. */ |
| rettv->v_type = VAR_STRING; |
| ! if (argvars[2].v_type != VAR_UNKNOWN) |
| ! { |
| ! 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 |
| ! rettv->vval.v_string = NULL; |
| } |
| |
| /* |
| |
| |
| |
| *** 5095,5103 **** |
| char_u ***file; |
| char *dirnames[]; |
| { |
| - char_u *matches; |
| char_u *s; |
| char_u *e; |
| garray_T ga; |
| int i; |
| int pat_len; |
| --- 5095,5103 ---- |
| char_u ***file; |
| char *dirnames[]; |
| { |
| char_u *s; |
| char_u *e; |
| + char_u *match; |
| garray_T ga; |
| int i; |
| int pat_len; |
| |
| *** 5116,5148 **** |
| return FAIL; |
| } |
| sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); |
| ! matches = globpath(p_rtp, s, 0); |
| vim_free(s); |
| ! if (matches == NULL) |
| ! continue; |
| |
| ! for (s = matches; *s != NUL; s = e) |
| { |
| ! e = vim_strchr(s, '\n'); |
| ! if (e == NULL) |
| ! e = s + STRLEN(s); |
| ! if (ga_grow(&ga, 1) == FAIL) |
| ! break; |
| ! if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) |
| ! { |
| ! for (s = e - 4; s > matches; mb_ptr_back(matches, s)) |
| ! if (*s == '\n' || vim_ispathsep(*s)) |
| ! break; |
| ! ++s; |
| ! ((char_u **)ga.ga_data)[ga.ga_len] = |
| ! vim_strnsave(s, (int)(e - s - 4)); |
| ! ++ga.ga_len; |
| ! } |
| ! if (*e != NUL) |
| ! ++e; |
| } |
| - vim_free(matches); |
| } |
| if (ga.ga_len == 0) |
| return FAIL; |
| |
| --- 5116,5142 ---- |
| return FAIL; |
| } |
| sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); |
| ! globpath(p_rtp, s, &ga, 0); |
| vim_free(s); |
| ! } |
| |
| ! for (i = 0; i < ga.ga_len; ++i) |
| ! { |
| ! match = ((char_u **)ga.ga_data)[i]; |
| ! s = match; |
| ! e = s + STRLEN(s); |
| ! if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) |
| { |
| ! e -= 4; |
| ! for (s = e; s > match; mb_ptr_back(match, s)) |
| ! if (s < match || vim_ispathsep(*s)) |
| ! break; |
| ! ++s; |
| ! *e = NUL; |
| ! mch_memmove(match, s, e - s + 1); |
| } |
| } |
| + |
| if (ga.ga_len == 0) |
| return FAIL; |
| |
| |
| *** 5160,5192 **** |
| #if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO) |
| /* |
| * Expand "file" for all comma-separated directories in "path". |
| ! * Returns an allocated string with all matches concatenated, separated by |
| ! * newlines. Returns NULL for an error or no matches. |
| */ |
| ! char_u * |
| ! globpath(path, file, expand_options) |
| char_u *path; |
| char_u *file; |
| int expand_options; |
| { |
| expand_T xpc; |
| char_u *buf; |
| - garray_T ga; |
| int i; |
| - int len; |
| int num_p; |
| char_u **p; |
| - char_u *cur = NULL; |
| |
| buf = alloc(MAXPATHL); |
| if (buf == NULL) |
| ! return NULL; |
| |
| ExpandInit(&xpc); |
| xpc.xp_context = EXPAND_FILES; |
| |
| - ga_init2(&ga, 1, 100); |
| - |
| /* Loop over all entries in {path}. */ |
| while (*path != NUL) |
| { |
| --- 5154,5181 ---- |
| #if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO) |
| /* |
| * Expand "file" for all comma-separated directories in "path". |
| ! * Adds the matches to "ga". Caller must init "ga". |
| */ |
| ! void |
| ! globpath(path, file, ga, expand_options) |
| char_u *path; |
| char_u *file; |
| + garray_T *ga; |
| int expand_options; |
| { |
| expand_T xpc; |
| char_u *buf; |
| int i; |
| int num_p; |
| char_u **p; |
| |
| buf = alloc(MAXPATHL); |
| if (buf == NULL) |
| ! return; |
| |
| ExpandInit(&xpc); |
| xpc.xp_context = EXPAND_FILES; |
| |
| /* Loop over all entries in {path}. */ |
| while (*path != NUL) |
| { |
| |
| *** 5207,5236 **** |
| WILD_SILENT|expand_options) != FAIL && num_p > 0) |
| { |
| 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, len) == OK) |
| { |
| - cur = (char_u *)ga.ga_data + ga.ga_len; |
| for (i = 0; i < num_p; ++i) |
| { |
| ! STRCPY(cur, p[i]); |
| ! cur += STRLEN(p[i]); |
| ! *cur++ = '\n'; |
| } |
| - ga.ga_len += len; |
| } |
| FreeWild(num_p, p); |
| } |
| } |
| } |
| - if (cur != NULL) |
| - *--cur = 0; /* Replace trailing newline with NUL */ |
| |
| vim_free(buf); |
| - return (char_u *)ga.ga_data; |
| } |
| |
| #endif |
| --- 5196,5218 ---- |
| WILD_SILENT|expand_options) != FAIL && num_p > 0) |
| { |
| ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); |
| |
| ! if (ga_grow(ga, num_p) == OK) |
| { |
| for (i = 0; i < num_p; ++i) |
| { |
| ! ((char_u **)ga->ga_data)[ga->ga_len] = |
| ! vim_strnsave(p[i], STRLEN(p[i])); |
| ! ++ga->ga_len; |
| } |
| } |
| + |
| FreeWild(num_p, p); |
| } |
| } |
| } |
| |
| vim_free(buf); |
| } |
| |
| #endif |
| |
| |
| |
| *** 10336,10344 **** |
| { |
| char_u *curdir; |
| garray_T path_ga; |
| - char_u *files = NULL; |
| - char_u *s; /* start */ |
| - char_u *e; /* end */ |
| char_u *paths = NULL; |
| |
| if ((curdir = alloc((unsigned)MAXPATHL)) == NULL) |
| --- 10336,10341 ---- |
| |
| *** 10351,10387 **** |
| if (path_ga.ga_len == 0) |
| return 0; |
| |
| ! paths = ga_concat_strings(&path_ga); |
| ga_clear_strings(&path_ga); |
| if (paths == NULL) |
| return 0; |
| |
| ! files = globpath(paths, pattern, (flags & EW_ICASE) ? WILD_ICASE : 0); |
| 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; |
| } |
| --- 10348,10360 ---- |
| if (path_ga.ga_len == 0) |
| return 0; |
| |
| ! paths = ga_concat_strings(&path_ga, ","); |
| ga_clear_strings(&path_ga); |
| if (paths == NULL) |
| return 0; |
| |
| ! globpath(paths, pattern, gap, (flags & EW_ICASE) ? WILD_ICASE : 0); |
| vim_free(paths); |
| |
| return gap->ga_len; |
| } |
| |
| |
| |
| *** 2087,2115 **** |
| |
| /* |
| * For a growing array that contains a list of strings: concatenate all the |
| ! * strings with a separating comma. |
| * Returns NULL when out of memory. |
| */ |
| char_u * |
| ! ga_concat_strings(gap) |
| garray_T *gap; |
| { |
| int i; |
| int len = 0; |
| char_u *s; |
| |
| for (i = 0; i < gap->ga_len; ++i) |
| ! len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + 1; |
| |
| s = alloc(len + 1); |
| if (s != NULL) |
| { |
| *s = NUL; |
| for (i = 0; i < gap->ga_len; ++i) |
| { |
| ! if (*s != NUL) |
| ! STRCAT(s, ","); |
| ! STRCAT(s, ((char_u **)(gap->ga_data))[i]); |
| } |
| } |
| return s; |
| --- 2087,2123 ---- |
| |
| /* |
| * For a growing array that contains a list of strings: concatenate all the |
| ! * strings with a separating "sep". |
| * Returns NULL when out of memory. |
| */ |
| char_u * |
| ! ga_concat_strings(gap, sep) |
| garray_T *gap; |
| + char *sep; |
| { |
| int i; |
| int len = 0; |
| + int sep_len = (int)STRLEN(sep); |
| char_u *s; |
| + char_u *p; |
| |
| for (i = 0; i < gap->ga_len; ++i) |
| ! len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len; |
| |
| s = alloc(len + 1); |
| if (s != NULL) |
| { |
| *s = NUL; |
| + p = s; |
| for (i = 0; i < gap->ga_len; ++i) |
| { |
| ! if (p != s) |
| ! { |
| ! STRCPY(p, sep); |
| ! p += sep_len; |
| ! } |
| ! STRCPY(p, ((char_u **)(gap->ga_data))[i]); |
| ! p += STRLEN(p); |
| } |
| } |
| return s; |
| |
| |
| |
| *** 32,38 **** |
| 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 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 init_history __ARGS((void)); |
| int get_histtype __ARGS((char_u *name)); |
| void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep)); |
| --- 32,38 ---- |
| 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 ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped)); |
| ! void globpath __ARGS((char_u *path, char_u *file, garray_T *ga, int expand_options)); |
| void init_history __ARGS((void)); |
| int get_histtype __ARGS((char_u *name)); |
| void add_to_history __ARGS((int histype, char_u *new_entry, int in_map, int sep)); |
| |
| |
| |
| *** 55,61 **** |
| void ga_init __ARGS((garray_T *gap)); |
| void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize)); |
| int ga_grow __ARGS((garray_T *gap, int n)); |
| ! char_u *ga_concat_strings __ARGS((garray_T *gap)); |
| void ga_concat __ARGS((garray_T *gap, char_u *s)); |
| void ga_append __ARGS((garray_T *gap, int c)); |
| void append_ga_line __ARGS((garray_T *gap)); |
| --- 55,61 ---- |
| void ga_init __ARGS((garray_T *gap)); |
| void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize)); |
| int ga_grow __ARGS((garray_T *gap, int n)); |
| ! char_u *ga_concat_strings __ARGS((garray_T *gap, char *sep)); |
| void ga_concat __ARGS((garray_T *gap, char_u *s)); |
| void ga_append __ARGS((garray_T *gap, int c)); |
| void append_ga_line __ARGS((garray_T *gap)); |
| |
| |
| |
| *** 5,16 **** |
| :so small.vim |
| :set shell=doesnotexist |
| :e test.out |
| ! :put =glob('Xxx\{') |
| ! :put =glob('Xxx\$') |
| :w! Xxx{ |
| :w! Xxx\$ |
| ! :put =glob('Xxx\{') |
| ! :put =glob('Xxx\$') |
| :w |
| :qa! |
| ENDTEST |
| --- 5,19 ---- |
| :so small.vim |
| :set shell=doesnotexist |
| :e test.out |
| ! :$put =glob('Xxx\{') |
| ! :$put =glob('Xxx\$') |
| :w! Xxx{ |
| :w! Xxx\$ |
| ! :$put =glob('Xxx\{') |
| ! :$put =glob('Xxx\$') |
| ! :" |
| ! :$put =string(globpath('sautest/autoload', '*.vim')) |
| ! :$put =string(globpath('sautest/autoload', '*.vim', 0, 1)) |
| :w |
| :qa! |
| ENDTEST |
| |
| |
| |
| *** 3,5 **** |
| --- 3,8 ---- |
| |
| Xxx{ |
| Xxx$ |
| + 'sautest/autoload/Test104.vim |
| + sautest/autoload/footest.vim' |
| + ['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim'] |
| |
| |
| |
| *** 736,737 **** |
| --- 736,739 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 279, |
| /**/ |
| |
| -- |
| hundred-and-one symptoms of being an internet addict: |
| 121. You ask for e-mail adresses instead of telephone numbers. |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ an exciting new programming language -- http://www.Zimbu.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |