diff src/option.c @ 17085:620e9011b685 v8.1.1542

patch 8.1.1542: an OptionSet autocommand does not get enough info commit https://github.com/vim/vim/commit/d7c968794710f338d491072171df48f96612cf72 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 15 17:12:48 2019 +0200 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)
author Bram Moolenaar <Bram@vim.org>
date Sat, 15 Jun 2019 17:15:05 +0200
parents d726d8cce996
children 1c2d05cb4d1d
line wrap: on
line diff
--- a/src/option.c
+++ b/src/option.c
@@ -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