]> granicus.if.org Git - vim/commitdiff
patch 8.2.2753: Vim9: cannot ignore an item in assignment unpack v8.2.2753
authorBram Moolenaar <Bram@vim.org>
Sat, 10 Apr 2021 20:35:43 +0000 (22:35 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 10 Apr 2021 20:35:43 +0000 (22:35 +0200)
Problem:    Vim9: cannot ignore an item in assignment unpack.
Solution:   Allow using an underscore.

runtime/doc/vim9.txt
src/eval.c
src/evalvars.c
src/testdir/test_vim9_assign.vim
src/version.c
src/vim.h
src/vim9compile.c

index 29fdab1488d467dfd908ba5a78c27820976a185e..6b676dfabd607d5d9f208f5d9f25e2272789c268 100644 (file)
@@ -335,6 +335,18 @@ The "g:" prefix is not needed for auto-load functions.
 Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
 used to repeat a `:substitute` command.
 
+For an unpack assignment the underscore can be used to ignore a list item,
+similar to how a function argument can be ignored: >
+       [a, _, c] = theList
+       [a, b; _] = longList
+
+<                                                      *E1092*
+Declaring more than one variable at a time, using the unpack notation, is
+currently not supported: >
+       var [v1, v2] = GetValues()  # Error!
+That is because the type needs to be inferred from the list item type, which
+isn't that easy.
+
 
 Constants ~
                                                *vim9-const* *vim9-final*
@@ -368,13 +380,6 @@ The constant only applies to the value itself, not what it refers to. >
        NAMES[1] = ["Emma"]     # Error!
        NAMES[1][0] = "Emma"    # OK, now females[0] == "Emma"
 
-<                                                      *E1092*
-Declaring more than one variable at a time, using the unpack notation, is
-currently not supported: >
-       var [v1, v2] = GetValues()  # Error!
-That is because the type needs to be inferred from the list item type, which
-isn't that easy.
-
 
 Omitting :call and :eval ~
 
index fe9d4ec2e4c8c594a3efdae57e7c869492fb111c..787243ed6568ba388965a83f19289f4451689886 100644 (file)
@@ -3514,7 +3514,7 @@ eval7(
        {
            int     flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 
-           if (in_vim9script() && len == 1 && *s == '_')
+           if (evaluate && in_vim9script() && len == 1 && *s == '_')
            {
                emsg(_(e_cannot_use_underscore_here));
                ret = FAIL;
index 5869a82a61ab271c83caafc71e11caec1453200f..b8a4352f8afd7c0e01636b109c559deee848f10a 100644 (file)
@@ -970,8 +970,8 @@ ex_let_vars(
     {
        arg = skipwhite(arg + 1);
        ++var_idx;
-       arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]",
-                                                                 op, var_idx);
+       arg = ex_let_one(arg, &item->li_tv, TRUE,
+                         flags | ASSIGN_UNPACK, (char_u *)",;]", op, var_idx);
        item = item->li_next;
        if (arg == NULL)
            return FAIL;
@@ -996,8 +996,8 @@ ex_let_vars(
            l->lv_refcount = 1;
            ++var_idx;
 
-           arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, flags,
-                                                  (char_u *)"]", op, var_idx);
+           arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
+                           flags | ASSIGN_UNPACK, (char_u *)"]", op, var_idx);
            clear_tv(&ltv);
            if (arg == NULL)
                return FAIL;
@@ -3190,7 +3190,9 @@ set_var_const(
     var_in_vim9script = is_script_local && current_script_is_vim9();
     if (var_in_vim9script && name[0] == '_' && name[1] == NUL)
     {
-       emsg(_(e_cannot_use_underscore_here));
+       // For "[a, _] = list" the underscore is ignored.
+       if ((flags & ASSIGN_UNPACK) == 0)
+           emsg(_(e_cannot_use_underscore_here));
        goto failed;
     }
 
index c35084d55046f4802035d65fa4df91c666060923..958b7b980944fa121d00d788cd6ebf02f6bb3c99 100644 (file)
@@ -256,6 +256,14 @@ def Test_assign_unpack()
     [v1, v2] = [1, 2]
     assert_equal(1, v1)
     assert_equal(2, v2)
+
+    [v1, _, v2, _] = [1, 99, 2, 77]
+    assert_equal(1, v1)
+    assert_equal(2, v2)
+
+    [v1, v2; _] = [1, 2, 3, 4, 5]
+    assert_equal(1, v1)
+    assert_equal(2, v2)
   END
   CheckDefAndScriptSuccess(lines)
 
index d266a1ad2eab9d52836d61d3522e451d8cfb9a77..c760738bea6f85dbacf2891542e9659b7e5942d7 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2753,
 /**/
     2752,
 /**/
index 7f4c99ad3698d1ee2efd1bd2283dc871b0fadbdf..31e181a13a299ac81011cde2256e991c577376b9 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2152,10 +2152,11 @@ typedef enum {
 } estack_arg_T;
 
 // Flags for assignment functions.
-#define ASSIGN_FINAL   1   // ":final"
-#define ASSIGN_CONST   2   // ":const"
-#define ASSIGN_NO_DECL 4   // "name = expr" without ":let"/":const"/":final"
-#define ASSIGN_DECL    8   // may declare variable if it does not exist
+#define ASSIGN_FINAL   0x01  // ":final"
+#define ASSIGN_CONST   0x02  // ":const"
+#define ASSIGN_NO_DECL 0x04  // "name = expr" without ":let"/":const"/":final"
+#define ASSIGN_DECL    0x08  // may declare variable if it does not exist
+#define ASSIGN_UNPACK  0x10  // using [a, b] = list
 
 #include "ex_cmds.h"       // Ex command defines
 #include "spell.h"         // spell checking stuff
index 02c75c4d6a6994a4cb41fb4b2bf019124e49d398..15d2c30e94ab520e46a869208af2f523263511d4 100644 (file)
@@ -6369,6 +6369,17 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
     {
        int             instr_count = -1;
 
+       if (var_start[0] == '_' && !eval_isnamec(var_start[1]))
+       {
+           // Ignore underscore in "[a, _, b] = list".
+           if (var_count > 0)
+           {
+               var_start = skipwhite(var_start + 2);
+               continue;
+           }
+           emsg(_(e_cannot_use_underscore_here));
+           goto theend;
+       }
        vim_free(lhs.lhs_name);
 
        /*
@@ -6388,11 +6399,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
            semsg(_(e_cannot_assign_to_constant), lhs.lhs_name);
            goto theend;
        }
-       if (is_decl && lhs.lhs_name[0] == '_' && lhs.lhs_name[1] == NUL)
-       {
-           emsg(_(e_cannot_use_underscore_here));
-           goto theend;
-       }
 
        if (!heredoc)
        {