]> granicus.if.org Git - vim/commitdiff
patch 8.1.1114: confusing overloaded operator "." for string concatenation v8.1.1114
authorBram Moolenaar <Bram@vim.org>
Thu, 4 Apr 2019 13:36:05 +0000 (15:36 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 4 Apr 2019 13:36:05 +0000 (15:36 +0200)
Problem:    Confusing overloaded operator "." for string concatenation.
Solution:   Add ".." for string concatenation.  Also "let a ..= b".

runtime/doc/eval.txt
src/eval.c
src/testdir/test_eval_stuff.vim
src/version.c

index c764f9aa0c05459579d6c633078bccf90575e594..0e301a3b45aa07e3ea885cf8e74d4aef25702d1d 100644 (file)
@@ -786,10 +786,10 @@ Expression syntax summary, from least to most significant:
        expr2 ? expr1 : expr1   if-then-else
 
 |expr2|        expr3
-       expr3 || expr3 ..       logical OR
+       expr3 || expr3 ...      logical OR
 
 |expr3|        expr4
-       expr4 && expr4 ..       logical AND
+       expr4 && expr4 ...      logical AND
 
 |expr4|        expr5
        expr5 == expr5          equal
@@ -811,14 +811,15 @@ Expression syntax summary, from least to most significant:
                                instance
 
 |expr5|        expr6
-       expr6 +  expr6 ..       number addition, list or blob concatenation
-       expr6 -  expr6 ..       number subtraction
-       expr6 .  expr6 ..       string concatenation
+       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 *  expr7 ...      number multiplication
+       expr7 /  expr7 ...      number division
+       expr7 %  expr7 ...      number modulo
 
 |expr7|        expr8
        ! expr7                 logical NOT
@@ -847,7 +848,7 @@ Expression syntax summary, from least to most significant:
        {args -> expr1}         lambda expression
 
 
-".." indicates that the operations in this level can be concatenated.
+"..." indicates that the operations in this level can be concatenated.
 Example: >
        &nu || &list && &shell == "csh"
 
@@ -1026,13 +1027,17 @@ can be matched like an ordinary character.  Examples:
 
 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   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-%*
@@ -5800,7 +5805,7 @@ islocked({expr})                                  *islocked()* *E786*
 isnan({expr})                                          *isnan()*
                Return |TRUE| if {expr} is a float with value NaN. >
                        echo isnan(0.0 / 0.0)
-<                      1 ~
+<                      1
 
                {only available when compiled with the |+float| feature}
 
index ec2dc9aa4aa7423a13a4ee1368670ff4e05feefe..78e2c60adde18ab9473cee9752ca5f5a68f126e6 100644 (file)
@@ -1234,6 +1234,7 @@ eval_foldexpr(char_u *arg, int *cp)
  * ":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,8 +1256,8 @@ ex_let(exarg_T *eap)
     if (argend > arg && argend[-1] == '.')  // for var.='str'
        --argend;
     expr = skipwhite(argend);
-    if (*expr != '=' && !(vim_strchr((char_u *)"+-*/%.", *expr) != NULL
-                         && expr[1] == '='))
+    if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%.", *expr) != NULL
+                          && expr[1] == '=') || STRNCMP(expr, "..=", 3) == 0))
     {
        /*
         * ":let" without "=": list variables
@@ -1286,7 +1287,11 @@ ex_let(exarg_T *eap)
        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,6 +3818,7 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
  *     +       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,6 +3878,8 @@ eval5(char_u **arg, typval_T *rettv, int evaluate)
        /*
         * Get the second variable.
         */
+       if (op == '.' && *(*arg + 1) == '.')  // .. string concatenation
+           ++*arg;
        *arg = skipwhite(*arg + 1);
        if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
        {
index f4b35983d9f71d85d0bfff8326c24911b7e6ce2b..6d61ce9244b22f8f2ac9f00a3de5c0abe6411751 100644 (file)
@@ -94,3 +94,32 @@ func Test_let_errmsg()
   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
index 38059505e347d4b29d03ef1f5d6c12ab465f1e8b..0b86e191f798fb90a453ed738cb46fe587e4ec2b 100644 (file)
@@ -771,6 +771,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1114,
 /**/
     1113,
 /**/