summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-04-04 15:36:05 +0200
committerBram Moolenaar <Bram@vim.org>2019-04-04 15:36:05 +0200
commit0f248b006c2574abc00c9aa7886d8f33620eb822 (patch)
treece29155e87c3dca50ab5b56b468647449bfee814
parenteb93f3f0e2b2ae65c5c3f55be3e62d64e3066f35 (diff)
patch 8.1.1114: confusing overloaded operator "." for string concatenationv8.1.1114
Problem: Confusing overloaded operator "." for string concatenation. Solution: Add ".." for string concatenation. Also "let a ..= b".
-rw-r--r--runtime/doc/eval.txt31
-rw-r--r--src/eval.c12
-rw-r--r--src/testdir/test_eval_stuff.vim29
-rw-r--r--src/version.c2
4 files changed, 59 insertions, 15 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index c764f9aa0c..0e301a3b45 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -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}
diff --git a/src/eval.c b/src/eval.c
index ec2dc9aa4a..78e2c60add 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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)
{
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index f4b35983d9..6d61ce9244 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 38059505e3..0b86e191f7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1114,
+/**/
1113,
/**/
1112,