To: vim_dev@googlegroups.com Subject: Patch 7.4.279 Fcc: outbox From: Bram Moolenaar 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 *** ../vim-7.4.278/runtime/doc/eval.txt 2014-04-23 17:43:37.350948683 +0200 --- runtime/doc/eval.txt 2014-05-07 17:38:03.045185916 +0200 *************** *** 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 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: > *** ../vim-7.4.278/src/eval.c 2014-05-07 17:31:32.473182497 +0200 --- src/eval.c 2014-05-07 18:06:29.541200854 +0200 *************** *** 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; } /* *** ../vim-7.4.278/src/ex_getln.c 2013-11-12 05:28:08.000000000 +0100 --- src/ex_getln.c 2014-05-07 18:11:49.281203653 +0200 *************** *** 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 *** ../vim-7.4.278/src/misc1.c 2014-05-07 15:10:17.657108310 +0200 --- src/misc1.c 2014-05-07 17:46:30.269190356 +0200 *************** *** 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; } *** ../vim-7.4.278/src/misc2.c 2014-03-23 15:12:29.927264336 +0100 --- src/misc2.c 2014-05-07 18:34:37.689215632 +0200 *************** *** 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; *** ../vim-7.4.278/src/proto/ex_getln.pro 2013-08-10 13:37:11.000000000 +0200 --- src/proto/ex_getln.pro 2014-05-07 17:52:42.457193614 +0200 *************** *** 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)); *** ../vim-7.4.278/src/proto/misc2.pro 2014-02-23 23:38:58.828760280 +0100 --- src/proto/misc2.pro 2014-05-07 17:52:36.189193559 +0200 *************** *** 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)); *** ../vim-7.4.278/src/testdir/test97.in 2013-08-02 14:55:50.000000000 +0200 --- src/testdir/test97.in 2014-05-07 18:27:59.213212144 +0200 *************** *** 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 *** ../vim-7.4.278/src/testdir/test97.ok 2013-07-03 16:14:50.000000000 +0200 --- src/testdir/test97.ok 2014-05-07 18:28:01.985212168 +0200 *************** *** 3,5 **** --- 3,8 ---- Xxx{ Xxx$ + 'sautest/autoload/Test104.vim + sautest/autoload/footest.vim' + ['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim'] *** ../vim-7.4.278/src/version.c 2014-05-07 17:31:32.473182497 +0200 --- src/version.c 2014-05-07 17:35:06.253184368 +0200 *************** *** 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 ///