]> granicus.if.org Git - vim/commitdiff
patch 8.2.2806: Vim9: using "++nr" as a command might not work v8.2.2806
authorBram Moolenaar <Bram@vim.org>
Sat, 24 Apr 2021 17:08:24 +0000 (19:08 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 24 Apr 2021 17:08:24 +0000 (19:08 +0200)
Problem:    Vim9: using "++nr" as a command might not work.
Solution:   Do not recognize "++" and "--" in a following line as addition or
            subtraction.

src/eval.c
src/ex_cmdidxs.h
src/ex_cmds.h
src/ex_docmd.c
src/proto/vim9script.pro
src/testdir/test_vim9_assign.vim
src/testdir/test_vim9_expr.vim
src/version.c
src/vim9compile.c
src/vim9script.c

index fbf4f57a522903876856121a8c5893da8d9ec61b..97a00f759eba0d822b954f8a23adbfddf1520238 100644 (file)
@@ -2856,12 +2856,15 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 
        // "." is only string concatenation when scriptversion is 1
        // "+=", "-=" and "..=" are assignments
+       // "++" and "--" on the next line are a separate command.
        p = eval_next_non_blank(*arg, evalarg, &getnext);
        op = *p;
        concat = op == '.' && (*(p + 1) == '.' || current_sctx.sc_version < 2);
        if ((op != '+' && op != '-' && !concat) || p[1] == '='
                                               || (p[1] == '.' && p[2] == '='))
            break;
+       if (getnext && (op == '+' || op == '-') && p[0] == p[1])
+           break;
 
        evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
        oplen = (concat && p[1] == '.') ? 2 : 1;
index 0d148d7d44695656ccba3e9107cd58f4110d6a5d..2696128af765b546f890da86afbaa72d9a3a0207 100644 (file)
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 577;
+static const int command_count = 579;
index 819cf732c8ac3ef8771f5884eb7c0701a9e86312..aee2e6f72e989a0d800f63224f965e6a69f1fba7 100644 (file)
@@ -1846,6 +1846,14 @@ EXCMD(CMD_X,             "X",            ex_X,
        EX_TRLBAR,
        ADDR_NONE),
 
+// Commands that are recognized only in find_ex_command().
+EXCMD(CMD_increment,   "++",           ex_incdec,
+       EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
+       ADDR_NONE),
+EXCMD(CMD_decrement,   "--",           ex_incdec,
+       EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
+       ADDR_NONE),
+
 #undef EXCMD
 
 #ifndef DO_DECLARE_EXCMD
index 0d87a894404485d92c7eddb6b8427e94409e2ff5..85fecbbbf1e30385908db20458ffce07c4437413 100644 (file)
@@ -3531,6 +3531,13 @@ find_ex_command(
            eap->cmdidx = CMD_eval;
            return eap->cmd;
        }
+
+       // Check for "++nr" and "--nr".
+       if (p == eap->cmd && p[0] == p[1] && (*p == '+' || *p == '-'))
+       {
+           eap->cmdidx = *p == '+' ? CMD_increment : CMD_decrement;
+           return eap->cmd + 2;
+       }
     }
 #endif
 
index cb5a30d2e0fcd806cb28d8c71b141fdeeb7eba14..2c4bd79606cc88574df924433788915124f29814 100644 (file)
@@ -5,6 +5,7 @@ void ex_vim9script(exarg_T *eap);
 int not_in_vim9(exarg_T *eap);
 int vim9_bad_comment(char_u *p);
 int vim9_comment_start(char_u *p);
+void ex_incdec(exarg_T *eap);
 void ex_export(exarg_T *eap);
 void free_imports_and_script_vars(int sid);
 void mark_imports_for_reload(int sid);
index a0175cd281f9fca666a6ba18bb6b25e418aa14db..246284c86f23dbcac2675492aabdf95476717d0e 100644 (file)
@@ -1837,5 +1837,21 @@ def Test_script_funcref_case()
   CheckScriptFailure(lines, 'E704:')
 enddef
 
+def Test_inc_dec()
+  var lines =<< trim END
+      var nr = 7
+      ++nr
+      echo nr
+      --nr
+      echo nr
+
+      var ll = [1, 2]
+      --ll[0]
+      ++ll[1]
+      echo ll
+  END
+  CheckDefAndScriptSuccess(lines)
+enddef
+
 
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
index fd9b406b24ecff9f0ead75e05aa9fe8d24b79f31..fdedd5f042dcb2f7c698fff726a84b7d8f819654 100644 (file)
@@ -2768,19 +2768,6 @@ def Test_expr7_negate_add()
     echo + +n
   END
   CheckDefAndScriptFailure(lines, 'E15:')
-
-  lines =<< trim END
-    var n = 12
-    :1
-    ++n
-  END
-  CheckDefAndScriptFailure(lines, 'E1050:')
-  lines =<< trim END
-    var n = 12
-    :1
-    --n
-  END
-  CheckDefAndScriptFailure(lines, 'E1050:')
 enddef
 
 def Test_expr7_legacy_script()
index 4c266eff6c2cf3298c3c69b6ff2a05cc71eeae82..1931aae031a8087a953e600a8f56c3e1987429de 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2806,
 /**/
     2805,
 /**/
index c65f1c37c6f4b4784a3a9b0df4845b6f04d5d0f4..a3154c3316adb228d64d02ae697c5c4925402e77 100644 (file)
@@ -4688,6 +4688,10 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
        op = may_peek_next_line(cctx, *arg, &next);
        if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
            break;
+       if (op[0] == op[1] && *op != '.' && next)
+           // Finding "++" or "--" on the next line is a separate command.
+           // But ".." is concatenation.
+           break;
        oplen = (*op == '.' ? 2 : 1);
        if (next != NULL)
        {
@@ -6395,6 +6399,7 @@ compile_assign_unlet(
  * "const name = expr"
  * "name = expr"
  * "arg" points to "name".
+ * "++arg" and "--arg"
  * Return NULL for an error.
  * Return "arg" if it does not look like a variable list.
  */
@@ -6413,6 +6418,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
     char_u     *op;
     int                oplen = 0;
     int                heredoc = FALSE;
+    int                incdec = FALSE;
     type_T     *rhs_type = &t_any;
     char_u     *sp;
     int                is_decl = is_decl_command(cmdidx);
@@ -6447,6 +6453,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
        error_white_both(op, oplen);
        return NULL;
     }
+    if (eap->cmdidx == CMD_increment || eap->cmdidx == CMD_decrement)
+    {
+       op = (char_u *)(eap->cmdidx == CMD_increment ? "+=" : "-=");
+       oplen = 2;
+       incdec = TRUE;
+    }
 
     if (heredoc)
     {
@@ -6571,23 +6583,31 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                            goto theend;
                    }
 
-                   // Compile the expression.  Temporarily hide the new local
-                   // variable here, it is not available to this expression.
-                   if (lhs.lhs_new_local)
-                       --cctx->ctx_locals.ga_len;
+                   // Compile the expression.
                    instr_count = instr->ga_len;
-                   wp = op + oplen;
-                   if (may_get_next_line_error(wp, &p, cctx) == FAIL)
+                   if (incdec)
                    {
+                       r = generate_PUSHNR(cctx, 1);
+                   }
+                   else
+                   {
+                       // Temporarily hide the new local variable here, it is
+                       // not available to this expression.
+                       if (lhs.lhs_new_local)
+                           --cctx->ctx_locals.ga_len;
+                       wp = op + oplen;
+                       if (may_get_next_line_error(wp, &p, cctx) == FAIL)
+                       {
+                           if (lhs.lhs_new_local)
+                               ++cctx->ctx_locals.ga_len;
+                           goto theend;
+                       }
+                       r = compile_expr0_ext(&p, cctx, &is_const);
                        if (lhs.lhs_new_local)
                            ++cctx->ctx_locals.ga_len;
-                       goto theend;
+                       if (r == FAIL)
+                           goto theend;
                    }
-                   r = compile_expr0_ext(&p, cctx, &is_const);
-                   if (lhs.lhs_new_local)
-                       ++cctx->ctx_locals.ga_len;
-                   if (r == FAIL)
-                       goto theend;
                }
                else if (semicolon && var_idx == var_count - 1)
                {
@@ -9018,9 +9038,11 @@ compile_def_function(
        /*
         * COMMAND after range
         * 'text'->func() should not be confused with 'a mark
+        * "++nr" and "--nr" are eval commands
         */
        cmd = ea.cmd;
-       if (*cmd != '\'' || starts_with_colon)
+       if (starts_with_colon || !(*cmd == '\''
+                       || (cmd[0] == cmd[1] && (*cmd == '+' || *cmd == '-'))))
        {
            ea.cmd = skip_range(ea.cmd, TRUE, NULL);
            if (ea.cmd > cmd)
@@ -9125,6 +9147,8 @@ compile_def_function(
            case CMD_var:
            case CMD_final:
            case CMD_const:
+           case CMD_increment:
+           case CMD_decrement:
                    line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
                    if (line == p)
                        line = NULL;
index ddbae781c612bc3177c8270fea3f4d1d0246b50f..02c04e2ea7a6d6750f4a3bf25cc9957ae4af153f 100644 (file)
@@ -159,6 +159,28 @@ vim9_comment_start(char_u *p)
 
 #if defined(FEAT_EVAL) || defined(PROTO)
 
+/*
+ * "++nr" and "--nr" commands.
+ */
+    void
+ex_incdec(exarg_T *eap)
+{
+    char_u     *cmd = eap->cmd;
+    size_t     len = STRLEN(eap->cmd) + 6;
+
+    // This works like "nr += 1" or "nr -= 1".
+    eap->cmd = alloc(len);
+    if (eap->cmd == NULL)
+       return;
+    vim_snprintf((char *)eap->cmd, len, "%s %c= 1", cmd + 2,
+                                    eap->cmdidx == CMD_increment ? '+' : '-');
+    eap->arg = eap->cmd;
+    eap->cmdidx = CMD_var;
+    ex_let(eap);
+    vim_free(eap->cmd);
+    eap->cmd = cmd;
+}
+
 /*
  * ":export let Name: type"
  * ":export const Name: type"