summaryrefslogtreecommitdiffstats
path: root/src/evalvars.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-09-24 23:13:51 +0200
committerChristian Brabandt <cb@256bit.org>2023-09-24 23:13:51 +0200
commitedcba96c0088210927558b0e2583f3b689f457c4 (patch)
tree615328c8c06bfd48a79098e7045c3998856b2d7f /src/evalvars.c
parent7398f367d5125eedfb4058c63a5d167fe8601e3d (diff)
patch 9.0.1933: Can change the type of a v: variable using if_luav9.0.1933
Problem: Can change the type of a v: variable using if_lua. Solution: Add additional handling of v: variables like :let. closes: #13161 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Diffstat (limited to 'src/evalvars.c')
-rw-r--r--src/evalvars.c106
1 files changed, 63 insertions, 43 deletions
diff --git a/src/evalvars.c b/src/evalvars.c
index bd096dfd7b..2438993942 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3673,6 +3673,62 @@ list_one_var_a(
}
/*
+ * Addition handling for setting a v: variable.
+ * Return TRUE if the variable should be set normally,
+ * FALSE if nothing else needs to be done.
+ */
+ int
+before_set_vvar(
+ char_u *varname,
+ dictitem_T *di,
+ typval_T *tv,
+ int copy,
+ int *type_error)
+{
+ if (di->di_tv.v_type == VAR_STRING)
+ {
+ VIM_CLEAR(di->di_tv.vval.v_string);
+ if (copy || tv->v_type != VAR_STRING)
+ {
+ char_u *val = tv_get_string(tv);
+
+ // Careful: when assigning to v:errmsg and
+ // tv_get_string() causes an error message the variable
+ // will already be set.
+ if (di->di_tv.vval.v_string == NULL)
+ di->di_tv.vval.v_string = vim_strsave(val);
+ }
+ else
+ {
+ // Take over the string to avoid an extra alloc/free.
+ di->di_tv.vval.v_string = tv->vval.v_string;
+ tv->vval.v_string = NULL;
+ }
+ return FALSE;
+ }
+ else if (di->di_tv.v_type == VAR_NUMBER)
+ {
+ di->di_tv.vval.v_number = tv_get_number(tv);
+ if (STRCMP(varname, "searchforward") == 0)
+ set_search_direction(di->di_tv.vval.v_number ? '/' : '?');
+#ifdef FEAT_SEARCH_EXTRA
+ else if (STRCMP(varname, "hlsearch") == 0)
+ {
+ no_hlsearch = !di->di_tv.vval.v_number;
+ redraw_all_later(UPD_SOME_VALID);
+ }
+#endif
+ return FALSE;
+ }
+ else if (di->di_tv.v_type != tv->v_type)
+ {
+ *type_error = TRUE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
* Set variable "name" to value in "tv".
* If the variable already exists, the value is updated.
* Otherwise the variable is created.
@@ -3877,51 +3933,15 @@ set_var_const(
// existing variable, need to clear the value
- // Handle setting internal di: variables separately where needed to
+ // Handle setting internal v: variables separately where needed to
// prevent changing the type.
- if (ht == &vimvarht)
+ int type_error = FALSE;
+ if (ht == &vimvarht
+ && !before_set_vvar(varname, di, tv, copy, &type_error))
{
- if (di->di_tv.v_type == VAR_STRING)
- {
- VIM_CLEAR(di->di_tv.vval.v_string);
- if (copy || tv->v_type != VAR_STRING)
- {
- char_u *val = tv_get_string(tv);
-
- // Careful: when assigning to v:errmsg and
- // tv_get_string() causes an error message the variable
- // will already be set.
- if (di->di_tv.vval.v_string == NULL)
- di->di_tv.vval.v_string = vim_strsave(val);
- }
- else
- {
- // Take over the string to avoid an extra alloc/free.
- di->di_tv.vval.v_string = tv->vval.v_string;
- tv->vval.v_string = NULL;
- }
- goto failed;
- }
- else if (di->di_tv.v_type == VAR_NUMBER)
- {
- di->di_tv.vval.v_number = tv_get_number(tv);
- if (STRCMP(varname, "searchforward") == 0)
- set_search_direction(di->di_tv.vval.v_number
- ? '/' : '?');
-#ifdef FEAT_SEARCH_EXTRA
- else if (STRCMP(varname, "hlsearch") == 0)
- {
- no_hlsearch = !di->di_tv.vval.v_number;
- redraw_all_later(UPD_SOME_VALID);
- }
-#endif
- goto failed;
- }
- else if (di->di_tv.v_type != tv->v_type)
- {
- semsg(_(e_setting_str_to_value_with_wrong_type), name);
- goto failed;
- }
+ if (type_error)
+ semsg(_(e_setting_v_str_to_value_with_wrong_type), varname);
+ goto failed;
}
clear_tv(&di->di_tv);