Patch 8.1.1114
Problem:    Confusing overloaded operator "." for string concatenation.
Solution:   Add ".." for string concatenation.  Also "let a ..= b".
Files:      src/eval.c, src/testdir/test_eval_stuff.vim, runtime/doc/eval.txt


*** ../vim-8.1.1113/src/eval.c  2019-03-30 20:04:05.024567549 +0100
--- src/eval.c  2019-04-04 15:23:48.333402717 +0200
***************
*** 1234,1239 ****
--- 1234,1240 ----
   * ":let var /= expr"         assignment command.
   * ":let var %= expr"         assignment command.
   * ":let var .= expr"         assignment command.
+  * ":let var ..= expr"                assignment command.
   * ":let [var1, var2] = expr" unpack list.
   */
      void
***************
*** 1255,1262 ****
      if (argend > arg && argend[-1] == '.')  // for var.='str'
        --argend;
      expr = skipwhite(argend);
!     if (*expr != '=' && !(vim_strchr((char_u *)"+-*/%.", *expr) != NULL
!                         && expr[1] == '='))
      {
        /*
         * ":let" without "=": list variables
--- 1256,1263 ----
      if (argend > arg && argend[-1] == '.')  // for var.='str'
        --argend;
      expr = skipwhite(argend);
!     if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%.", *expr) != NULL
!                          && expr[1] == '=') || STRNCMP(expr, "..=", 3) == 0))
      {
        /*
         * ":let" without "=": list variables
***************
*** 1286,1292 ****
--- 1287,1297 ----
        if (*expr != '=')
        {
            if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
+           {
                op[0] = *expr;   // +=, -=, *=, /=, %= or .=
+               if (expr[0] == '.' && expr[1] == '.') // ..=
+                   ++expr;
+           }
            expr = skipwhite(expr + 2);
        }
        else
***************
*** 3813,3818 ****
--- 3818,3824 ----
   *    +       number addition
   *    -       number subtraction
   *    .       string concatenation
+  *    ..      string concatenation
   *
   * "arg" must point to the first non-white of the expression.
   * "arg" is advanced to the next non-white after the recognized expression.
***************
*** 3872,3877 ****
--- 3878,3885 ----
        /*
         * Get the second variable.
         */
+       if (op == '.' && *(*arg + 1) == '.')  // .. string concatenation
+           ++*arg;
        *arg = skipwhite(*arg + 1);
        if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
        {
*** ../vim-8.1.1113/src/testdir/test_eval_stuff.vim     2019-01-24 
13:58:05.817568979 +0100
--- src/testdir/test_eval_stuff.vim     2019-04-04 15:17:26.815290594 +0200
***************
*** 94,96 ****
--- 94,125 ----
    call assert_fails('let v:errmsg = []', 'E730:')
    let v:errmsg = ''
  endfunc
+ 
+ func Test_string_concatenation()
+   call assert_equal('ab', 'a'.'b')
+   call assert_equal('ab', 'a' .'b')
+   call assert_equal('ab', 'a'. 'b')
+   call assert_equal('ab', 'a' . 'b')
+ 
+   call assert_equal('ab', 'a'..'b')
+   call assert_equal('ab', 'a' ..'b')
+   call assert_equal('ab', 'a'.. 'b')
+   call assert_equal('ab', 'a' .. 'b')
+ 
+   let a = 'a'
+   let b = 'b'
+   let a .= b
+   call assert_equal('ab', a)
+ 
+   let a = 'a'
+   let a.=b
+   call assert_equal('ab', a)
+ 
+   let a = 'a'
+   let a ..= b
+   call assert_equal('ab', a)
+ 
+   let a = 'a'
+   let a..=b
+   call assert_equal('ab', a)
+ endfunc
*** ../vim-8.1.1113/runtime/doc/eval.txt        2019-04-04 13:44:31.031594540 
+0200
--- runtime/doc/eval.txt        2019-04-04 15:26:47.752500735 +0200
***************
*** 773,782 ****
        expr2 ? expr1 : expr1   if-then-else
  
  |expr2|       expr3
!       expr3 || expr3 ..       logical OR
  
  |expr3|       expr4
!       expr4 && expr4 ..       logical AND
  
  |expr4|       expr5
        expr5 == expr5          equal
--- 786,795 ----
        expr2 ? expr1 : expr1   if-then-else
  
  |expr2|       expr3
!       expr3 || expr3 ...      logical OR
  
  |expr3|       expr4
!       expr4 && expr4 ...      logical AND
  
  |expr4|       expr5
        expr5 == expr5          equal
***************
*** 793,810 ****
        etc.                    As above, append ? for ignoring case, # for
                                matching case
  
!       expr5 is expr5          same |List| instance
!       expr5 isnot expr5       different |List| instance
  
  |expr5|       expr6
!       expr6 +  expr6 ..       number addition, list or blob concatenation
!       expr6 -  expr6 ..       number subtraction
!       expr6 .  expr6 ..       string concatenation
  
  |expr6|       expr7
!       expr7 *  expr7 ..       number multiplication
!       expr7 /  expr7 ..       number division
!       expr7 %  expr7 ..       number modulo
  
  |expr7|       expr8
        ! expr7                 logical NOT
--- 806,825 ----
        etc.                    As above, append ? for ignoring case, # for
                                matching case
  
!       expr5 is expr5          same |List|, |Dictionary| or |Blob| instance
!       expr5 isnot expr5       different |List|, |Dictionary| or |Blob|
!                               instance
  
  |expr5|       expr6
!       expr6 +  expr6 ...      number addition, list or blob concatenation
!       expr6 -  expr6 ...      number subtraction
!       expr6 .  expr6 ...      string concatenation
!       expr6 .. expr6 ...      string concatenation
  
  |expr6|       expr7
!       expr7 *  expr7 ...      number multiplication
!       expr7 /  expr7 ...      number division
!       expr7 %  expr7 ...      number modulo
  
  |expr7|       expr8
        ! expr7                 logical NOT
***************
*** 833,839 ****
        {args -> expr1}         lambda expression
  
  
! ".." indicates that the operations in this level can be concatenated.
  Example: >
        &nu || &list && &shell == "csh"
  
--- 848,854 ----
        {args -> expr1}         lambda expression
  
  
! "..." indicates that the operations in this level can be concatenated.
  Example: >
        &nu || &list && &shell == "csh"
  
***************
*** 1012,1027 ****
  
  expr5 and expr6                                               *expr5* *expr6*
  ---------------
! expr6 +        expr6 ..       Number addition or |List| concatenation *expr-+*
! expr6 -        expr6 ..       Number subtraction                      *expr--*
! expr6 .        expr6 ..       String concatenation                    *expr-.*
  
  For |Lists| only "+" is possible and then both expr6 must be a list.  The
  result is a new list with the two lists Concatenated.
  
! expr7 *        expr7 ..       Number multiplication                   
*expr-star*
! expr7 /        expr7 ..       Number division                         *expr-/*
! expr7 %        expr7 ..       Number modulo                           *expr-%*
  
  For all, except ".", Strings are converted to Numbers.
  For bitwise operators see |and()|, |or()| and |xor()|.
--- 1027,1046 ----
  
  expr5 and expr6                                               *expr5* *expr6*
  ---------------
! expr6 + expr6   Number addition, |List| or |Blob| concatenation       *expr-+*
! expr6 - expr6   Number subtraction                            *expr--*
! expr6 . expr6   String concatenation                          *expr-.*
! expr6 .. expr6  String concatenation                          *expr-..*
  
  For |Lists| only "+" is possible and then both expr6 must be a list.  The
  result is a new list with the two lists Concatenated.
  
! For String concatenation ".." is preferred, since "." is ambiguous, it is also
! used for |Dict| member access and floating point numbers.
! 
! expr7 * expr7  Number multiplication                          *expr-star*
! expr7 / expr7  Number division                                        *expr-/*
! expr7 % expr7  Number modulo                                  *expr-%*
  
  For all, except ".", Strings are converted to Numbers.
  For bitwise operators see |and()|, |or()| and |xor()|.
***************
*** 1080,1085 ****
--- 1099,1111 ----
  
  expr8                                                 *expr8*
  -----
+ This expression is either |expr9| or a sequence of the alternatives below,
+ in any order.  E.g., these are all possible:
+       expr9[expr1].name
+       expr9.name[expr1]
+       expr9(expr1, ...)[expr1].name
+ 
+ 
  expr8[expr1]          item of String or |List|        *expr-[]* *E111*
                                                        *E909* *subscript*
  If expr8 is a Number or String this results in a String that contains the
*** ../vim-8.1.1113/src/version.c       2019-04-04 15:04:32.966792195 +0200
--- src/version.c       2019-04-04 15:32:15.826390483 +0200
***************
*** 773,774 ****
--- 773,776 ----
  {   /* Add new patch number below this line */
+ /**/
+     1114,
  /**/

-- 
Press any key to continue, press any other key to quit.

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
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