1
0
forked from aniani/vim

patch 8.2.2753: Vim9: cannot ignore an item in assignment unpack

Problem:    Vim9: cannot ignore an item in assignment unpack.
Solution:   Allow using an underscore.
This commit is contained in:
Bram Moolenaar
2021-04-10 22:35:43 +02:00
parent e8e3078184
commit f93bbd0262
7 changed files with 46 additions and 22 deletions

View 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 ~

View 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;

View 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;
}

View 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)

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2753,
/**/
2752,
/**/

View File

@@ -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

View 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)
{