Patch 7.4.241
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)
Files:      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


*** ../vim-7.4.240/runtime/doc/eval.txt 2014-04-02 12:12:04.151981514 +0200
--- runtime/doc/eval.txt        2014-04-02 17:56:51.163696948 +0200
***************
*** 1989,1995 ****
                                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()
  substitute( {expr}, {pat}, {sub}, {flags})
                                String  all {pat} in {expr} replaced with {sub}
  synID( {lnum}, {col}, {trans})        Number  syntax ID at {lnum} and {col}
--- 1990,1997 ----
                                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}[, {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}
***************
*** 5784,5795 ****
                Ambiguous, this function's return value depends on 'ambiwidth'.
                Also see |strlen()|, |strdisplaywidth()| and |strchars()|.
  
! submatch({nr})                                                *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.
                Also see |sub-replace-expression|.
                Example: >
                        :s/\d\+/\=submatch(0) + 1/
  <             This finds the first number in the line and adds one to it.
--- 5798,5820 ----
                Ambiguous, this function's return value depends on 'ambiwidth'.
                Also see |strlen()|, |strdisplaywidth()| and |strchars()|.
  
! 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.
*** ../vim-7.4.240/src/eval.c   2014-04-02 12:12:04.159981514 +0200
--- src/eval.c  2014-04-02 18:16:33.011680690 +0200
***************
*** 8129,8135 ****
      {"strridx",               2, 3, f_strridx},
      {"strtrans",      1, 1, f_strtrans},
      {"strwidth",      1, 1, f_strwidth},
!     {"submatch",      1, 1, f_submatch},
      {"substitute",    4, 4, f_substitute},
      {"synID",         3, 3, f_synID},
      {"synIDattr",     2, 3, f_synIDattr},
--- 8129,8135 ----
      {"strridx",               2, 3, f_strridx},
      {"strtrans",      1, 1, f_strtrans},
      {"strwidth",      1, 1, f_strwidth},
!     {"submatch",      1, 2, f_submatch},
      {"substitute",    4, 4, f_substitute},
      {"synID",         3, 3, f_synID},
      {"synIDattr",     2, 3, f_synIDattr},
***************
*** 17890,17898 ****
      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));
  }
  
  /*
--- 17890,17921 ----
      typval_T  *argvars;
      typval_T  *rettv;
  {
!     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);
!     }
  }
  
  /*
*** ../vim-7.4.240/src/proto/regexp.pro 2013-08-10 13:37:24.000000000 +0200
--- src/proto/regexp.pro        2014-04-02 18:19:12.415678498 +0200
***************
*** 10,15 ****
--- 10,16 ----
  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));
*** ../vim-7.4.240/src/regexp.c 2014-03-23 15:12:29.931264336 +0100
--- src/regexp.c        2014-04-02 18:59:34.431645181 +0200
***************
*** 7897,7902 ****
--- 7897,7981 ----
  
      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 =
*** ../vim-7.4.240/src/testdir/test79.in        2013-04-13 11:16:38.000000000 
+0200
--- src/testdir/test79.in       2014-04-02 17:51:01.807701753 +0200
***************
*** 181,190 ****
--- 181,192 ----
  :set cpo&
  /^TEST/
  j:s/A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\=submatch(0) . 
submatch(9) . submatch(8) . submatch(7) . submatch(6) . submatch(5) . 
submatch(4) . submatch(3) . submatch(2) . submatch(1)/
+ j:s/B\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\=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)])/
  ENDTEST
  
  TEST_5:
  A123456789
+ B123456789
  
  STARTTEST
  :set magic&
***************
*** 209,214 ****
--- 211,219 ----
  /^TEST_7/
  j:s/A./\=submatch(0)/
  j:s/B./\=submatch(0)/
+ j:s/C./\=strtrans(string(submatch(0, 1)))/
+ j:s/D.\nD/\=strtrans(string(submatch(0, 1)))/
+ j:s/E\_.\{-}E/\=strtrans(string(submatch(0, 1)))/
  /^Q$
  :s/Q[^\n]Q/\=submatch(0)."foobar"/
  :" Avoid :s error breaks dotest map on Windows.
***************
*** 217,226 ****
--- 222,240 ----
  TEST_7:
  A
A
  B

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui