Patch 8.2.1518
Problem: Vim9: cannot assign to local option.
Solution: Skip over "&l:" and "&g:". (closes #6749)
Files: src/ex_docmd.c, src/proto/
ex_docmd.pro, src/testdir/vim9.vim,
src/vim9compile.c src/testdir/test_vim9_script.vim
*** ../vim-8.2.1517/src/ex_docmd.c 2020-08-20 18:02:42.711595041 +0200
--- src/ex_docmd.c 2020-08-23 19:32:01.395258400 +0200
***************
*** 3243,3248 ****
--- 3243,3269 ----
}
/*
+ * If "start" points "&opt", "&l:opt", "&g:opt" or "$ENV" return a pointer to
+ * the name. Otherwise just return "start".
+ */
+ char_u *
+ skip_option_env_lead(char_u *start)
+ {
+ char_u *name = start;
+
+ if (*start == '&')
+ {
+ if ((start[1] == 'l' || start[1] == 'g') && start[2] == ':')
+ name += 3;
+ else
+ name += 1;
+ }
+ else if (*start == '$')
+ name += 1;
+ return name;
+ }
+
+ /*
* Find an Ex command by its name, either built-in or user.
* Start of the name can be found at eap->cmd.
* Sets eap->cmdidx and returns a pointer to char after the command name.
***************
*** 3273,3281 ****
p = eap->cmd;
if (lookup != NULL)
{
! // Skip over first char for "&opt = val", "$ENV = val" and "@r = val".
! char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$')
! ? eap->cmd + 1 : eap->cmd;
if (vim_strchr((char_u *)"{('[\"@", *p) != NULL
|| ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
--- 3294,3300 ----
p = eap->cmd;
if (lookup != NULL)
{
! char_u *pskip = skip_option_env_lead(eap->cmd);
if (vim_strchr((char_u *)"{('[\"@", *p) != NULL
|| ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
*** ../vim-8.2.1517/src/proto/
ex_docmd.pro 2020-08-20 15:02:38.536534973 +0200
--- src/proto/
ex_docmd.pro 2020-08-23 19:06:02.903459281 +0200
***************
*** 10,15 ****
--- 10,16 ----
void undo_cmdmod(exarg_T *eap, int save_msg_scroll);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
int checkforcmd(char_u **pp, char *cmd, int len);
+ char_u *skip_option_env_lead(char_u *start);
char_u *find_ex_command(exarg_T *eap, int *full, void *(*lookup)(char_u *, size_t, cctx_T *), cctx_T *cctx);
int modifier_len(char_u *cmd);
int cmd_exists(char_u *name);
*** ../vim-8.2.1517/src/testdir/vim9.vim 2020-08-21 22:36:43.666719887 +0200
--- src/testdir/vim9.vim 2020-08-23 18:05:39.970945615 +0200
***************
*** 41,46 ****
--- 41,51 ----
delete('Xdef')
enddef
+ def CheckDefAndScriptSuccess(lines: list<string>)
+ CheckDefSuccess(lines)
+ CheckScriptSuccess(['vim9script'] + lines)
+ enddef
+
" Check that a command fails both when used in a :def function and when used
" in Vim9 script.
def CheckScriptAndDefFailure(lines: list<string>, error: string, lnum = -3)
*** ../vim-8.2.1517/src/vim9compile.c 2020-08-23 15:21:52.050677280 +0200
--- src/vim9compile.c 2020-08-23 19:29:56.671575070 +0200
***************
*** 4550,4557 ****
p = var_start + 2;
else
{
! p = (*var_start == '&' || *var_start == '$')
! ? var_start + 1 : var_start;
p = to_name_end(p, TRUE);
}
--- 4550,4557 ----
p = var_start + 2;
else
{
! // skip over the leading "&", "&l:", "&g:" and "$"
! p = skip_option_env_lead(var_start);
p = to_name_end(p, TRUE);
}
***************
*** 4595,4602 ****
}
cc = *p;
*p = NUL;
! opt_type = get_option_value(var_start + 1, &numval,
! NULL, opt_flags);
*p = cc;
if (opt_type == -3)
{
--- 4595,4602 ----
}
cc = *p;
*p = NUL;
! opt_type = get_option_value(skip_option_env_lead(var_start),
! &numval, NULL, opt_flags);
*p = cc;
if (opt_type == -3)
{
***************
*** 5131,5137 ****
switch (dest)
{
case dest_option:
! generate_STOREOPT(cctx, name + 1, opt_flags);
break;
case dest_global:
// include g: with the name, easier to execute that way
--- 5131,5138 ----
switch (dest)
{
case dest_option:
! generate_STOREOPT(cctx, skip_option_env_lead(name),
! opt_flags);
break;
case dest_global:
// include g: with the name, easier to execute that way
*** ../vim-8.2.1517/src/testdir/test_vim9_script.vim 2020-08-23 16:29:07.737130996 +0200
--- src/testdir/test_vim9_script.vim 2020-08-23 19:33:15.939063805 +0200
***************
*** 110,121 ****
endif
lines =<< trim END
- vim9script
&ts = 6
&ts += 3
assert_equal(9, &ts)
END
! CheckScriptSuccess(lines)
CheckDefFailure(['¬ex += 3'], 'E113:')
CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
--- 110,130 ----
endif
lines =<< trim END
&ts = 6
&ts += 3
assert_equal(9, &ts)
+
+ &l:ts = 6
+ assert_equal(6, &ts)
+ &l:ts += 2
+ assert_equal(8, &ts)
+
+ &g:ts = 6
+ assert_equal(6, &g:ts)
+ &g:ts += 2
+ assert_equal(8, &g:ts)
END
! CheckDefAndScriptSuccess(lines)
CheckDefFailure(['¬ex += 3'], 'E113:')
CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
***************
*** 163,181 ****
call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
- @a = 'areg'
- @a ..= 'add'
- assert_equal('aregadd', @a)
- call CheckDefFailure(['@a += "more"'], 'E1051:')
- call CheckDefFailure(['@a += 123'], 'E1012:')
-
lines =<< trim END
- vim9script
@c = 'areg'
@c ..= 'add'
assert_equal('aregadd', @c)
END
! call CheckScriptSuccess(lines)
v:errmsg = 'none'
v:errmsg ..= 'again'
--- 172,186 ----
call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
lines =<< trim END
@c = 'areg'
@c ..= 'add'
assert_equal('aregadd', @c)
END
! CheckDefAndScriptSuccess(lines)
!
! call CheckDefFailure(['@a += "more"'], 'E1051:')
! call CheckDefFailure(['@a += 123'], 'E1012:')
v:errmsg = 'none'
v:errmsg ..= 'again'
*** ../vim-8.2.1517/src/version.c 2020-08-23 17:33:43.773458055 +0200
--- src/version.c 2020-08-23 19:05:57.075477667 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1518,
/**/
--
There is a fine line between courage and foolishness.
Unfortunately, it's not a fence.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language --
http://www.Zimbu.org ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///