aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c38
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);