0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

patch 8.1.1542: an OptionSet autocommand does not get enough info

Problem:    An OptionSet autocommand does not get enough info.
Solution:   Add v:option_command, v:option_oldlocal and v:option_oldglobal.
            (Latrice Wilgus, closes #4118)
This commit is contained in:
Bram Moolenaar
2019-06-15 17:12:48 +02:00
parent bffc50494d
commit d7c9687947
9 changed files with 750 additions and 85 deletions

View File

@@ -4336,12 +4336,25 @@ set_title_defaults(void)
#endif
#if defined(FEAT_EVAL)
/*
* Trigger the OptionSet autocommand.
* "opt_idx" is the index of the option being set.
* "opt_flags" can be OPT_LOCAL etc.
* "oldval" the old value
* "oldval_l" the old local value (only non-NULL if global and local value
* are set)
* "oldval_g" the old global value (only non-NULL if global and local value
* are set)
* "newval" the new value
*/
static void
trigger_optionsset_string(
int opt_idx,
int opt_flags,
char_u *oldval,
char_u *newval)
char_u *oldval,
char_u *oldval_l,
char_u *oldval_g,
char_u *newval)
{
// Don't do this recursively.
if (oldval != NULL && newval != NULL
@@ -4354,6 +4367,27 @@ trigger_optionsset_string(
set_vim_var_string(VV_OPTION_OLD, oldval, -1);
set_vim_var_string(VV_OPTION_NEW, newval, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
if (opt_flags & OPT_LOCAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
}
if (opt_flags & OPT_GLOBAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
}
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
}
if (opt_flags & OPT_MODELINE)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
}
apply_autocmds(EVENT_OPTIONSET,
(char_u *)options[opt_idx].fullname, NULL, FALSE, NULL);
reset_v_option_vars();
@@ -4836,8 +4870,12 @@ do_set(
char_u *oldval = NULL; /* previous value if *varp */
char_u *newval;
char_u *origval = NULL;
char_u *origval_l = NULL;
char_u *origval_g = NULL;
#if defined(FEAT_EVAL)
char_u *saved_origval = NULL;
char_u *saved_origval_l = NULL;
char_u *saved_origval_g = NULL;
char_u *saved_newval = NULL;
#endif
unsigned newlen;
@@ -4857,8 +4895,23 @@ do_set(
* new value is valid. */
oldval = *(char_u **)varp;
/* When setting the local value of a global
* option, the old value may be the global value. */
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
origval_l = *(char_u **)get_varp_scope(
&(options[opt_idx]), OPT_LOCAL);
origval_g = *(char_u **)get_varp_scope(
&(options[opt_idx]), OPT_GLOBAL);
// A global-local string option might have an empty
// option as value to indicate that the global
// value should be used.
if (((int)options[opt_idx].indir & PV_BOTH)
&& origval_l == empty_option)
origval_l = origval_g;
}
// When setting the local value of a global
// option, the old value may be the global value.
if (((int)options[opt_idx].indir & PV_BOTH)
&& (opt_flags & OPT_LOCAL))
origval = *(char_u **)get_varp(
@@ -4944,6 +4997,10 @@ do_set(
vim_free(oldval);
if (origval == oldval)
origval = *(char_u **)varp;
if (origval_l == oldval)
origval_l = *(char_u **)varp;
if (origval_g == oldval)
origval_g = *(char_u **)varp;
oldval = *(char_u **)varp;
}
/*
@@ -5201,6 +5258,10 @@ do_set(
/* newval (and varp) may become invalid if the
* buffer is closed by autocommands. */
saved_newval = vim_strsave(newval);
if (origval_l != NULL)
saved_origval_l = vim_strsave(origval_l);
if (origval_g != NULL)
saved_origval_g = vim_strsave(origval_g);
}
#endif
@@ -5234,9 +5295,13 @@ do_set(
#if defined(FEAT_EVAL)
if (errmsg == NULL)
trigger_optionsset_string(opt_idx, opt_flags,
saved_origval, saved_newval);
trigger_optionsset_string(
opt_idx, opt_flags, saved_origval,
saved_origval_l, saved_origval_g,
saved_newval);
vim_free(saved_origval);
vim_free(saved_origval_l);
vim_free(saved_origval_g);
vim_free(saved_newval);
#endif
/* If error detected, print the error message. */
@@ -6070,8 +6135,12 @@ set_string_option(
char_u *s;
char_u **varp;
char_u *oldval;
char_u *oldval_l = NULL;
char_u *oldval_g = NULL;
#if defined(FEAT_EVAL)
char_u *saved_oldval = NULL;
char_u *saved_oldval_l = NULL;
char_u *saved_oldval_g = NULL;
char_u *saved_newval = NULL;
#endif
char *r = NULL;
@@ -6089,6 +6158,13 @@ set_string_option(
? OPT_GLOBAL : OPT_LOCAL)
: opt_flags);
oldval = *varp;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
oldval_l = *(char_u **)get_varp_scope(&(options[opt_idx]),
OPT_LOCAL);
oldval_g = *(char_u **)get_varp_scope(&(options[opt_idx]),
OPT_GLOBAL);
}
*varp = s;
#if defined(FEAT_EVAL)
@@ -6098,6 +6174,10 @@ set_string_option(
# endif
)
{
if (oldval_l != NULL)
saved_oldval_l = vim_strsave(oldval_l);
if (oldval_g != NULL)
saved_oldval_g = vim_strsave(oldval_g);
saved_oldval = vim_strsave(oldval);
saved_newval = vim_strsave(s);
}
@@ -6110,8 +6190,11 @@ set_string_option(
/* call autocommand after handling side effects */
if (r == NULL)
trigger_optionsset_string(opt_idx, opt_flags,
saved_oldval, saved_newval);
saved_oldval, saved_oldval_l,
saved_oldval_g, saved_newval);
vim_free(saved_oldval);
vim_free(saved_oldval_l);
vim_free(saved_oldval_g);
vim_free(saved_newval);
#endif
}
@@ -8442,6 +8525,7 @@ set_bool_option(
int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
{
int old_value = *(int *)varp;
int old_global_value = 0;
/* Disallow changing some options from secure mode */
if ((secure
@@ -8451,6 +8535,13 @@ set_bool_option(
) && (options[opt_idx].flags & P_SECURE))
return e_secure;
// Save the global value before changing anything. This is needed as for
// a global-only option setting the "local value" in fact sets the global
// value (since there is only one value).
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
old_global_value = *(int *)get_varp_scope(&(options[opt_idx]),
OPT_GLOBAL);
*(int *)varp = value; /* set the new value */
#ifdef FEAT_EVAL
/* Remember where the option was set. */
@@ -8976,15 +9067,40 @@ set_bool_option(
// Don't do this while starting up or recursively.
if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
{
char_u buf_old[2], buf_new[2], buf_type[7];
char_u buf_old[2], buf_old_global[2], buf_new[2], buf_type[7];
vim_snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE);
vim_snprintf((char *)buf_old_global, 2, "%d",
old_global_value ? TRUE: FALSE);
vim_snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE);
vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
vim_snprintf((char *)buf_type, 7, "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET, (char_u *) options[opt_idx].fullname, NULL, FALSE, NULL);
if (opt_flags & OPT_LOCAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
}
if (opt_flags & OPT_GLOBAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
}
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
}
if (opt_flags & OPT_MODELINE)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
}
apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
NULL, FALSE, NULL);
reset_v_option_vars();
}
#endif
@@ -9014,8 +9130,10 @@ set_num_option(
{
char *errmsg = NULL;
long old_value = *(long *)varp;
long old_Rows = Rows; /* remember old Rows */
long old_Columns = Columns; /* remember old Columns */
long old_global_value = 0; // only used when setting a local and
// global option
long old_Rows = Rows; // remember old Rows
long old_Columns = Columns; // remember old Columns
long *pp = (long *)varp;
/* Disallow changing some options from secure mode. */
@@ -9026,6 +9144,12 @@ set_num_option(
) && (options[opt_idx].flags & P_SECURE))
return e_secure;
// Save the global value before changing anything. This is needed as for
// a global-only option setting the "local value" infact sets the global
// value (since there is only one value).
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
*pp = value;
#ifdef FEAT_EVAL
/* Remember where the option was set. */
@@ -9533,15 +9657,37 @@ set_num_option(
// Don't do this while starting up, failure or recursively.
if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
{
char_u buf_old[11], buf_new[11], buf_type[7];
char_u buf_old[11], buf_old_global[11], buf_new[11], buf_type[7];
vim_snprintf((char *)buf_old, 10, "%ld", old_value);
vim_snprintf((char *)buf_old_global, 10, "%ld", old_global_value);
vim_snprintf((char *)buf_new, 10, "%ld", value);
vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
apply_autocmds(EVENT_OPTIONSET, (char_u *) options[opt_idx].fullname, NULL, FALSE, NULL);
if (opt_flags & OPT_LOCAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
}
if (opt_flags & OPT_GLOBAL)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
}
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
}
if (opt_flags & OPT_MODELINE)
{
set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
}
apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
NULL, FALSE, NULL);
reset_v_option_vars();
}
#endif