Mercurial > vim
changeset 24426:78343859f42d v8.2.2753
patch 8.2.2753: Vim9: cannot ignore an item in assignment unpack
Commit: https://github.com/vim/vim/commit/f93bbd026205f36915312193784f987ad49fb114
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Apr 10 22:35:43 2021 +0200
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 10 Apr 2021 22:45:04 +0200 |
parents | 6e8954e66929 |
children | e255d418a91d |
files | 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 |
diffstat | 7 files changed, 46 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -335,6 +335,18 @@ The "g:" prefix is not needed for auto-l 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 i 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 ~
--- 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;
--- 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), <v, FALSE, flags, - (char_u *)"]", op, var_idx); + arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, + flags | ASSIGN_UNPACK, (char_u *)"]", op, var_idx); clear_tv(<v); 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; }
--- 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)
--- 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,
--- 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
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6369,6 +6369,17 @@ compile_assignment(char_u *arg, exarg_T { 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 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) {