0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

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 Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
used to repeat a `:substitute` command. 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 ~ Constants ~
*vim9-const* *vim9-final* *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] = ["Emma"] # Error!
NAMES[1][0] = "Emma" # OK, now females[0] == "Emma" 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 ~ Omitting :call and :eval ~

View File

@@ -3514,7 +3514,7 @@ eval7(
{ {
int flags = evalarg == NULL ? 0 : evalarg->eval_flags; 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)); emsg(_(e_cannot_use_underscore_here));
ret = FAIL; ret = FAIL;

View File

@@ -970,8 +970,8 @@ ex_let_vars(
{ {
arg = skipwhite(arg + 1); arg = skipwhite(arg + 1);
++var_idx; ++var_idx;
arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]", arg = ex_let_one(arg, &item->li_tv, TRUE,
op, var_idx); flags | ASSIGN_UNPACK, (char_u *)",;]", op, var_idx);
item = item->li_next; item = item->li_next;
if (arg == NULL) if (arg == NULL)
return FAIL; return FAIL;
@@ -996,8 +996,8 @@ ex_let_vars(
l->lv_refcount = 1; l->lv_refcount = 1;
++var_idx; ++var_idx;
arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, flags, arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
(char_u *)"]", op, var_idx); flags | ASSIGN_UNPACK, (char_u *)"]", op, var_idx);
clear_tv(&ltv); clear_tv(&ltv);
if (arg == NULL) if (arg == NULL)
return FAIL; return FAIL;
@@ -3190,7 +3190,9 @@ set_var_const(
var_in_vim9script = is_script_local && current_script_is_vim9(); var_in_vim9script = is_script_local && current_script_is_vim9();
if (var_in_vim9script && name[0] == '_' && name[1] == NUL) 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; goto failed;
} }

View File

@@ -256,6 +256,14 @@ def Test_assign_unpack()
[v1, v2] = [1, 2] [v1, v2] = [1, 2]
assert_equal(1, v1) assert_equal(1, v1)
assert_equal(2, v2) 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 END
CheckDefAndScriptSuccess(lines) CheckDefAndScriptSuccess(lines)

View File

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

View File

@@ -2152,10 +2152,11 @@ typedef enum {
} estack_arg_T; } estack_arg_T;
// Flags for assignment functions. // Flags for assignment functions.
#define ASSIGN_FINAL 1 // ":final" #define ASSIGN_FINAL 0x01 // ":final"
#define ASSIGN_CONST 2 // ":const" #define ASSIGN_CONST 0x02 // ":const"
#define ASSIGN_NO_DECL 4 // "name = expr" without ":let"/":const"/":final" #define ASSIGN_NO_DECL 0x04 // "name = expr" without ":let"/":const"/":final"
#define ASSIGN_DECL 8 // may declare variable if it does not exist #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 "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff #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; 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); 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); semsg(_(e_cannot_assign_to_constant), lhs.lhs_name);
goto theend; goto theend;
} }
if (is_decl && lhs.lhs_name[0] == '_' && lhs.lhs_name[1] == NUL)
{
emsg(_(e_cannot_use_underscore_here));
goto theend;
}
if (!heredoc) if (!heredoc)
{ {