diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index deaed17926..1640729c94 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1442,7 +1442,11 @@ int 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 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 ex_let(exarg_T *eap) @@ -1465,8 +1469,8 @@ void ex_let(exarg_T *eap) 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 if (*arg == '[') { EMSG(_(e_invarg)); @@ -1488,8 +1492,11 @@ void ex_let(exarg_T *eap) op[0] = '='; op[1] = NUL; if (*expr != '=') { - if (vim_strchr((char_u *)"+-.", *expr) != NULL) { - op[0] = *expr; // +=, -=, .= + if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL) { + op[0] = *expr; // +=, -=, *=, /=, %= or .= + if (expr[0] == '.' && expr[1] == '.') { // ..= + expr++; + } } expr = skipwhite(expr + 2); } else { @@ -1864,7 +1871,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, if (len == 0) { EMSG2(_(e_invarg2), name - 1); } else { - if (op != NULL && (*op == '+' || *op == '-')) { + if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) { EMSG2(_(e_letwrong), op); } else if (endchars != NULL && vim_strchr(endchars, *skipwhite(arg)) == NULL) { @@ -1927,10 +1934,12 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, s = NULL; // don't set the value } else { if (opt_type == 1) { // number - if (*op == '+') { - n = numval + n; - } else { - n = numval - n; + switch (*op) { + case '+': n = numval + n; break; + case '-': n = numval - n; break; + case '*': n = numval * n; break; + case '/': n = numval / n; break; + case '%': n = numval % n; break; } } else if (opt_type == 0 && stringval != NULL) { // string char *const oldstringval = stringval; @@ -1951,7 +1960,7 @@ static char_u *ex_let_one(char_u *arg, typval_T *const tv, // ":let @r = expr": Set register contents. } else if (*arg == '@') { arg++; - if (op != NULL && (*op == '+' || *op == '-')) { + if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) { emsgf(_(e_letwrong), op); } else if (endchars != NULL && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { @@ -2350,7 +2359,8 @@ static void clear_lval(lval_T *lp) /* * Set a variable that was parsed by get_lval() to "rettv". * "endp" points to just after the parsed name. - * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=". + * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=", + * "%" for "%=", "." for ".=" or "=" for "=". */ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, const char_u *op) @@ -2365,7 +2375,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, if (op != NULL && *op != '=') { typval_T tv; - // handle +=, -= and .= + // handle +=, -=, *=, /=, %= and .= di = NULL; if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name), &tv, &di, true, false) == OK) { @@ -3783,6 +3793,7 @@ static int 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. @@ -3830,6 +3841,9 @@ static int 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) { tv_clear(rettv); |