]> granicus.if.org Git - vim/commitdiff
updated for version 7.4.241 v7.4.241
authorBram Moolenaar <Bram@vim.org>
Wed, 2 Apr 2014 17:00:58 +0000 (19:00 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 2 Apr 2014 17:00:58 +0000 (19:00 +0200)
Problem:    The string returned by submatch() does not distinguish between a
            NL from a line break and a NL that stands for a NUL character.
Solution:   Add a second argument to return a list. (ZyX)

runtime/doc/eval.txt
src/eval.c
src/proto/regexp.pro
src/regexp.c
src/testdir/test79.in
src/testdir/test79.ok
src/testdir/test80.in
src/testdir/test80.ok
src/version.c

index 007c7f7469262e4e58c2b9a64e81625d889f1d2e..cdf8d72bb26f3c09361cf8d008216ff00b3331ee 100644 (file)
@@ -1990,7 +1990,8 @@ strridx( {haystack}, {needle} [, {start}])
                                Number  last index of {needle} in {haystack}
 strtrans( {expr})              String  translate string to make it printable
 strwidth( {expr})              Number  display cell length of the String {expr}
-submatch( {nr})                        String  specific match in ":s" or substitute()
+submatch( {nr}[, {list}])      String or List
+                                       specific match in ":s" or substitute()
 substitute( {expr}, {pat}, {sub}, {flags})
                                String  all {pat} in {expr} replaced with {sub}
 synID( {lnum}, {col}, {trans}) Number  syntax ID at {lnum} and {col}
@@ -5797,12 +5798,23 @@ strwidth({expr})                                        *strwidth()*
                Ambiguous, this function's return value depends on 'ambiwidth'.
                Also see |strlen()|, |strdisplaywidth()| and |strchars()|.
 
-submatch({nr})                                         *submatch()*
+submatch({nr}[, {list}])                               *submatch()*
                Only for an expression in a |:substitute| command or
                substitute() function.
                Returns the {nr}'th submatch of the matched text.  When {nr}
                is 0 the whole matched text is returned.
+               Note that a NL in the string can stand for a line break of a
+               multi-line match or a NUL character in the text.
                Also see |sub-replace-expression|.
+
+               If {list} is present and non-zero then submatch() returns 
+               a list of strings, similar to |getline()| with two arguments. 
+               NL characters in the text represent NUL characters in the
+               text.
+               Only returns more than one item for |:substitute|, inside
+               |substitute()| this list will always contain one or zero
+               items, since there are no real line breaks.
+
                Example: >
                        :s/\d\+/\=submatch(0) + 1/
 <              This finds the first number in the line and adds one to it.
index 05f91b303e3584ff21d2f9d7907fbe60597ed794..7b682572cf06f54de7840b3716404f29472250fe 100644 (file)
@@ -8129,7 +8129,7 @@ static struct fst
     {"strridx",                2, 3, f_strridx},
     {"strtrans",       1, 1, f_strtrans},
     {"strwidth",       1, 1, f_strwidth},
-    {"submatch",       1, 1, f_submatch},
+    {"submatch",       1, 2, f_submatch},
     {"substitute",     4, 4, f_substitute},
     {"synID",          3, 3, f_synID},
     {"synIDattr",      2, 3, f_synIDattr},
@@ -17890,9 +17890,32 @@ f_submatch(argvars, rettv)
     typval_T   *argvars;
     typval_T   *rettv;
 {
-    rettv->v_type = VAR_STRING;
-    rettv->vval.v_string =
-                   reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
+    int                error = FALSE;
+    char_u     **match;
+    char_u     **s;
+    listitem_T *li;
+    int                no;
+    int                retList = 0;
+
+    no = (int)get_tv_number_chk(&argvars[0], &error);
+    if (error)
+       return;
+    error = FALSE;
+    if (argvars[1].v_type != VAR_UNKNOWN)
+       retList = get_tv_number_chk(&argvars[1], &error);
+    if (error)
+       return;
+
+    if (retList == 0)
+    {
+       rettv->v_type = VAR_STRING;
+       rettv->vval.v_string = reg_submatch(no);
+    }
+    else
+    {
+       rettv->v_type = VAR_LIST;
+       rettv->vval.v_list = reg_submatch_list(no);
+    }
 }
 
 /*
index 38c9c33c4e932966088b47e0a525cc2972b29133..a42c5944a85f67f38ce6540eb7e0d1b84b990e67 100644 (file)
@@ -10,6 +10,7 @@ char_u *regtilde __ARGS((char_u *source, int magic));
 int vim_regsub __ARGS((regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash));
 int vim_regsub_multi __ARGS((regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash));
 char_u *reg_submatch __ARGS((int no));
+list_T *reg_submatch_list __ARGS((int no));
 regprog_T *vim_regcomp __ARGS((char_u *expr_arg, int re_flags));
 void vim_regfree __ARGS((regprog_T *prog));
 int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
index 32a51884b243b757036daad6dbc6ba6c23334593..0a590f66d7f02a1a264f9a93b6c084178bf1c0b8 100644 (file)
@@ -7897,6 +7897,85 @@ reg_submatch(no)
 
     return retval;
 }
+
+/*
+ * Used for the submatch() function with the optional non-zero argument: get
+ * the list of strings from the n'th submatch in allocated memory with NULs
+ * represented in NLs.
+ * Returns a list of allocated strings.  Returns NULL when not in a ":s"
+ * command, for a non-existing submatch and for any error.
+ */
+    list_T *
+reg_submatch_list(no)
+    int                no;
+{
+    char_u     *s;
+    linenr_T   slnum;
+    linenr_T   elnum;
+    colnr_T    scol;
+    colnr_T    ecol;
+    int                i;
+    list_T     *list;
+    int                error = FALSE;
+
+    if (!can_f_submatch || no < 0)
+       return NULL;
+
+    if (submatch_match == NULL)
+    {
+       slnum = submatch_mmatch->startpos[no].lnum;
+       elnum = submatch_mmatch->endpos[no].lnum;
+       if (slnum < 0 || elnum < 0)
+           return NULL;
+
+       scol = submatch_mmatch->startpos[no].col;
+       ecol = submatch_mmatch->endpos[no].col;
+
+       list = list_alloc();
+       if (list == NULL)
+           return NULL;
+
+       s = reg_getline_submatch(slnum) + scol;
+       if (slnum == elnum)
+       {
+           if (list_append_string(list, s, ecol - scol) == FAIL)
+               error = TRUE;
+       }
+       else
+       {
+           if (list_append_string(list, s, -1) == FAIL)
+               error = TRUE;
+           for (i = 1; i < elnum - slnum; i++)
+           {
+               s = reg_getline_submatch(slnum + i);
+               if (list_append_string(list, s, -1) == FAIL)
+                   error = TRUE;
+           }
+           s = reg_getline_submatch(elnum);
+           if (list_append_string(list, s, ecol) == FAIL)
+               error = TRUE;
+       }
+    }
+    else
+    {
+       s = submatch_match->startp[no];
+       if (s == NULL || submatch_match->endp[no] == NULL)
+           return NULL;
+       list = list_alloc();
+       if (list == NULL)
+           return NULL;
+       if (list_append_string(list, s,
+                                (int)(submatch_match->endp[no] - s)) == FAIL)
+           error = TRUE;
+    }
+
+    if (error)
+    {
+       list_free(list, TRUE);
+       return NULL;
+    }
+    return list;
+}
 #endif
 
 static regengine_T bt_regengine =
index f15ecc0f8dc07e351bf7ac6e1a8e1cba63db1fbb..56955c23182a8809b9aa233afbc8f6d1148d07c1 100644 (file)
Binary files a/src/testdir/test79.in and b/src/testdir/test79.in differ
index bb30d140525facb55d0b400578271a9d90da5534..0f6ea4545106dbc331076866a7effa74ebcd0927 100644 (file)
Binary files a/src/testdir/test79.ok and b/src/testdir/test79.ok differ
index c62fdc02b273edef561514178b575c4e2b6da2ef..406fb6dac7250f94dae9f596af23b8c00d9ff266 100644 (file)
@@ -117,6 +117,7 @@ STARTTEST
 :set cpo&
 :$put =\"\n\nTEST_5:\"
 :$put =substitute('A123456789', 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', '\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . submatch(6) . submatch(5) . submatch(4) . submatch(3) . submatch(2) . submatch(1)', '')
+:$put =substitute('A123456789', 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', '\=string([submatch(0, 1), submatch(9, 1), submatch(8, 1), submatch(7, 1), submatch(6, 1), submatch(5, 1), submatch(4, 1), submatch(3, 1), submatch(2, 1), submatch(1, 1)])', '')
 /^TEST_6
 ENDTEST
 
@@ -142,6 +143,7 @@ STARTTEST
 :$put =\"\n\nTEST_7:\"
 :$put =substitute('A\16\rA', 'A.', '\=submatch(0)', '')
 :$put =substitute(\"B\nB\", 'B.', '\=submatch(0)', '')
+:$put =substitute(\"B\nB\", 'B.', '\=string(submatch(0, 1))', '')
 :$put =substitute('-bb', '\zeb', 'a', 'g')
 :$put =substitute('-bb', '\ze', 'c', 'g')
 /^TEST_8
index 2b79d377a73f5fb652f2bf78df2263b5112eb69d..b42f604a07b14ac67e61fd1fe9f2f12a82c62310 100644 (file)
@@ -90,6 +90,7 @@ l
 
 TEST_5:
 A123456789987654321
+[['A123456789'], ['9'], ['8'], ['7'], ['6'], ['5'], ['4'], ['3'], ['2'], ['1']]
 
 
 TEST_6:
@@ -103,6 +104,8 @@ TEST_7:
 A\rA
 B
 B
+['B
+']B
 -abab
 c-cbcbc
 
index 472a7fad034b53927cad71315d9c613cfbcda014..fbfb5e66a147babe5957720869d85b4be92b7ee0 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    241,
 /**/
     240,
 /**/