summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-10 22:35:43 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-10 22:35:43 +0200
commitf93bbd026205f36915312193784f987ad49fb114 (patch)
tree3d33a10b9e526aa7ed613bb4113df3406025632a
parente8e307818495d1a5d821df9bd4bde83add0520e5 (diff)
downloadvim-git-8.2.2753.tar.gz
patch 8.2.2753: Vim9: cannot ignore an item in assignment unpackv8.2.2753
Problem: Vim9: cannot ignore an item in assignment unpack. Solution: Allow using an underscore.
-rw-r--r--runtime/doc/vim9.txt19
-rw-r--r--src/eval.c2
-rw-r--r--src/evalvars.c12
-rw-r--r--src/testdir/test_vim9_assign.vim8
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h9
-rw-r--r--src/vim9compile.c16
7 files changed, 46 insertions, 22 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index 29fdab148..6b676dfab 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -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 ~
diff --git a/src/eval.c b/src/eval.c
index fe9d4ec2e..787243ed6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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;
diff --git a/src/evalvars.c b/src/evalvars.c
index 5869a82a6..b8a4352f8 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -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;
}
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index c35084d55..958b7b980 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -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)
diff --git a/src/version.c b/src/version.c
index d266a1ad2..c760738be 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2753,
+/**/
2752,
/**/
2751,
diff --git a/src/vim.h b/src/vim.h
index 7f4c99ad3..31e181a13 100644
--- 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
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 02c75c4d6..15d2c30e9 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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)
{