summaryrefslogtreecommitdiffstats
path: root/src/evalvars.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evalvars.c')
-rw-r--r--src/evalvars.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/evalvars.c b/src/evalvars.c
index 8e42c5a..de9d5b2 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3830,7 +3830,7 @@ set_var(
* If the variable already exists and "is_const" is FALSE the value is updated.
* Otherwise the variable is created.
*/
- void
+ int
set_var_const(
char_u *name,
scid_T sid,
@@ -3854,6 +3854,7 @@ set_var_const(
int var_in_autoload = FALSE;
int flags = flags_arg;
int free_tv_arg = !copy; // free tv_arg if not used
+ int rc = FAIL;
if (sid != 0)
{
@@ -3977,7 +3978,14 @@ set_var_const(
if (check_typval_is_value(&di->di_tv) == FAIL)
goto failed;
- if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
+ // List and Blob types can be modified in-place using the "+="
+ // compound operator. For other types, this is not allowed.
+ int type_inplace_modifiable =
+ (di->di_tv.v_type == VAR_LIST || di->di_tv.v_type == VAR_BLOB);
+
+ if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0
+ && ((flags & ASSIGN_COMPOUND_OP) == 0
+ || !type_inplace_modifiable))
{
where_T where = WHERE_INIT;
svar_T *sv = find_typval_in_script(&di->di_tv, sid, TRUE);
@@ -3998,7 +4006,11 @@ set_var_const(
}
}
- if ((flags & ASSIGN_FOR_LOOP) == 0
+ // Modifying a final variable with a List value using the "+="
+ // operator is allowed. For other types, it is not allowed.
+ if (((flags & ASSIGN_FOR_LOOP) == 0
+ && ((flags & ASSIGN_COMPOUND_OP) == 0
+ || !type_inplace_modifiable))
? var_check_permission(di, name) == FAIL
: var_check_ro(di->di_flags, name, FALSE))
goto failed;
@@ -4116,10 +4128,14 @@ set_var_const(
// values.
item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
+ rc = OK;
+
failed:
vim_free(name_tofree);
if (free_tv_arg)
clear_tv(tv_arg);
+
+ return rc;
}
/*
@@ -4832,6 +4848,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
{
tabpage_T *save_curtab;
tabpage_T *tp;
+ tabpage_T *save_lu_tp;
char_u *varname, *tabvarname;
typval_T *varp;
@@ -4851,6 +4868,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
return;
save_curtab = curtab;
+ save_lu_tp = lastused_tabpage;
goto_tabpage_tp(tp, FALSE, FALSE);
tabvarname = alloc(STRLEN(varname) + 3);
@@ -4862,9 +4880,13 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
vim_free(tabvarname);
}
- // Restore current tabpage
+ // Restore current tabpage and last accessed tabpage.
if (valid_tabpage(save_curtab))
+ {
goto_tabpage_tp(save_curtab, FALSE, FALSE);
+ if (valid_tabpage(save_lu_tp))
+ lastused_tabpage = save_lu_tp;
+ }
}
/*
@@ -4924,6 +4946,10 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
if (*varname == '&')
{
aco_save_T aco;
+ // safe the current window position, it could
+ // change because of 'scrollbind' window-local
+ // options
+ linenr_T old_topline = curwin->w_topline;
// Set curbuf to be our buf, temporarily.
aucmd_prepbuf(&aco, buf);
@@ -4935,6 +4961,7 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
// reset notion of buffer
aucmd_restbuf(&aco);
}
+ curwin->w_topline = old_topline;
}
else
{