changeset 6935:4db70c94226b v7.4.786

patch 7.4.786 Problem: It is not possible for a plugin to adjust to a changed setting. Solution: Add the OptionSet autocommand event. (Christian Brabandt)
author Bram Moolenaar <bram@vim.org>
date Fri, 17 Jul 2015 17:38:22 +0200
parents be7bd53ad376
children 6f7f9d8992a1
files runtime/doc/autocmd.txt runtime/doc/eval.txt src/eval.c src/fileio.c src/option.c src/proto/eval.pro src/testdir/Make_amiga.mak src/testdir/Make_dos.mak src/testdir/Make_ming.mak src/testdir/Make_os2.mak src/testdir/Make_vms.mms src/testdir/Makefile src/testdir/test_autocmd_option.in src/testdir/test_autocmd_option.ok src/version.c src/vim.h
diffstat 16 files changed, 354 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -259,6 +259,7 @@ Name			triggered by ~
 |Syntax|		when the 'syntax' option has been set
 |EncodingChanged|	after the 'encoding' option has been changed
 |TermChanged|		after the value of 'term' has changed
+|OptionSet|		after setting any option
 
 	Startup and exit
 |VimEnter|		after doing all the startup stuff
@@ -744,6 +745,27 @@ MenuPopup			Just before showing the popu
 					o	Operator-pending
 					i	Insert
 					c	Command line
+							*OptionSet*
+OptionSet			After setting an option.  The pattern is
+				matched against the long option name.
+				The |v:option_old| variable indicates the
+				old option value, |v:option_new| variable
+				indicates the newly set value, the
+				|v:option_type| variable indicates whether
+				it's global or local scoped and |<amatch>|
+				indicates what option has been set.
+
+				Is not triggered on startup and for the 'key'
+				option for obvious reasons.
+
+				Note: It's a bad idea, to reset an option
+				during this autocommand, since this will
+				probably break plugins. You can always use
+				|noa| to prevent triggering this autocommand.
+				Could be used, to check for existence of the
+				'backupdir' and 'undodir' options and create
+				directories, if they don't exist yet.
+
 							*QuickFixCmdPre*
 QuickFixCmdPre			Before a quickfix command is run (|:make|,
 				|:lmake|, |:grep|, |:lgrep|, |:grepadd|,
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1535,6 +1535,15 @@ v:oldfiles	List of file names that is lo
 		than String this will cause trouble.
 		{only when compiled with the |+viminfo| feature}
 
+						    *v:option_new*
+v:option_new    New value of the option. Valid while executing an |OptionSet|
+		autocommand.
+						    *v:option_old*
+v:option_old    Old value of the option. Valid while executing an |OptionSet|
+		autocommand.
+						    *v:option_type*
+v:option_type   Scope of the set command. Valid while executing an
+		|OptionSet| autocommand. Can be either "global" or "local"
 					*v:operator* *operator-variable*
 v:operator	The last operator given in Normal mode.  This is a single
 		character except for commands starting with <g> or <z>,
--- a/src/eval.c
+++ b/src/eval.c
@@ -365,6 +365,9 @@ static struct vimvar
     {VV_NAME("windowid",	 VAR_NUMBER), VV_RO},
     {VV_NAME("progpath",	 VAR_STRING), VV_RO},
     {VV_NAME("completed_item",	 VAR_DICT), VV_RO},
+    {VV_NAME("option_new",	 VAR_STRING), VV_RO},
+    {VV_NAME("option_old",	 VAR_STRING), VV_RO},
+    {VV_NAME("option_type",	 VAR_STRING), VV_RO},
 };
 
 /* shorthand */
@@ -24720,6 +24723,16 @@ ex_oldfiles(eap)
     }
 }
 
+/* reset v:option_new, v:option_old and v:option_type */
+    void
+reset_v_option_vars()
+{
+    set_vim_var_string(VV_OPTION_NEW,  NULL, -1);
+    set_vim_var_string(VV_OPTION_OLD,  NULL, -1);
+    set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
+}
+
+
 #endif /* FEAT_EVAL */
 
 
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -7699,6 +7699,7 @@ static struct event_name
     {"InsertLeave",	EVENT_INSERTLEAVE},
     {"InsertCharPre",	EVENT_INSERTCHARPRE},
     {"MenuPopup",	EVENT_MENUPOPUP},
+    {"OptionSet",	EVENT_OPTIONSET},
     {"QuickFixCmdPost",	EVENT_QUICKFIXCMDPOST},
     {"QuickFixCmdPre",	EVENT_QUICKFIXCMDPRE},
     {"QuitPre",		EVENT_QUITPRE},
@@ -7736,7 +7737,7 @@ static AutoPat *first_autopat[NUM_EVENTS
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 /*
@@ -9321,7 +9322,7 @@ apply_autocmds_group(event, fname, fname
      */
     if (fname_io == NULL)
     {
-	if (event == EVENT_COLORSCHEME)
+	if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET)
 	    autocmd_fname = NULL;
 	else if (fname != NULL && *fname != NUL)
 	    autocmd_fname = fname;
@@ -9385,6 +9386,7 @@ apply_autocmds_group(event, fname, fname
 		|| event == EVENT_SPELLFILEMISSING
 		|| event == EVENT_QUICKFIXCMDPRE
 		|| event == EVENT_COLORSCHEME
+		|| event == EVENT_OPTIONSET
 		|| event == EVENT_QUICKFIXCMDPOST)
 	    fname = vim_strsave(fname);
 	else
--- a/src/option.c
+++ b/src/option.c
@@ -4592,9 +4592,12 @@ do_set(arg, opt_flags)
 		    {
 			char_u	    *save_arg = NULL;
 			char_u	    *s = NULL;
-			char_u	    *oldval;	/* previous value if *varp */
+			char_u	    *oldval = NULL;	/* previous value if *varp */
 			char_u	    *newval;
-			char_u	    *origval;
+			char_u	    *origval = NULL;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+			char_u	    *saved_origval = NULL;
+#endif
 			unsigned    newlen;
 			int	    comma;
 			int	    bs;
@@ -4914,6 +4917,14 @@ do_set(arg, opt_flags)
 			/* Set the new value. */
 			*(char_u **)(varp) = newval;
 
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+			if (!starting && options[opt_idx].indir != PV_KEY
+							   && origval != NULL)
+			    /* origval may be freed by
+			     * did_set_string_option(), make a copy. */
+			    saved_origval = vim_strsave(origval);
+#endif
+
 			/* Handle side effects, and set the global value for
 			 * ":set" on local options. */
 			errmsg = did_set_string_option(opt_idx, (char_u **)varp,
@@ -4922,6 +4933,24 @@ do_set(arg, opt_flags)
 			/* If error detected, print the error message. */
 			if (errmsg != NULL)
 			    goto skip;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+			if (saved_origval != NULL)
+			{
+			    char_u buf_type[7];
+
+			    sprintf((char *)buf_type, "%s",
+				(opt_flags & OPT_LOCAL) ? "local" : "global");
+			    set_vim_var_string(VV_OPTION_NEW, newval, -1);
+			    set_vim_var_string(VV_OPTION_OLD, saved_origval, -1);
+			    set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+			    apply_autocmds(EVENT_OPTIONSET,
+					  (char_u *)options[opt_idx].fullname,
+				NULL, FALSE, NULL);
+			    reset_v_option_vars();
+			    vim_free(saved_origval);
+			}
+#endif
+
 		    }
 		    else	    /* key code option */
 		    {
@@ -5668,6 +5697,9 @@ set_string_option(opt_idx, value, opt_fl
     char_u	*s;
     char_u	**varp;
     char_u	*oldval;
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+    char_u	*saved_oldval = NULL;
+#endif
     char_u	*r = NULL;
 
     if (options[opt_idx].var == NULL)	/* don't set hidden option */
@@ -5683,9 +5715,30 @@ set_string_option(opt_idx, value, opt_fl
 		    : opt_flags);
 	oldval = *varp;
 	*varp = s;
+
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+	if (!starting && options[opt_idx].indir != PV_KEY)
+	    saved_oldval = vim_strsave(oldval);
+#endif
 	if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
 							   opt_flags)) == NULL)
 	    did_set_option(opt_idx, opt_flags, TRUE);
+
+	/* call autocomamnd after handling side effects */
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+	if (saved_oldval != NULL)
+	{
+	    char_u buf_type[7];
+	    sprintf((char *)buf_type, "%s",
+		(opt_flags & OPT_LOCAL) ? "local" : "global");
+	    set_vim_var_string(VV_OPTION_NEW, s, -1);
+	    set_vim_var_string(VV_OPTION_OLD, oldval, -1);
+	    set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+	    apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, NULL, FALSE, NULL);
+	    reset_v_option_vars();
+	    vim_free(saved_oldval);
+	}
+#endif
     }
     return r;
 }
@@ -8230,8 +8283,25 @@ set_bool_option(opt_idx, varp, value, op
      * End of handling side effects for bool options.
      */
 
+    /* after handling side effects, call autocommand */
+
     options[opt_idx].flags |= P_WAS_SET;
 
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+    if (!starting)
+    {
+	char_u buf_old[2], buf_new[2], buf_type[7];
+	snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE);
+	snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE);
+	sprintf((char *)buf_type, "%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);
+	reset_v_option_vars();
+    }
+#endif
+
     comp_col();			    /* in case 'ruler' or 'showcmd' changed */
     if (curwin->w_curswant != MAXCOL
 		     && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
@@ -8767,6 +8837,21 @@ set_num_option(opt_idx, varp, value, err
 
     options[opt_idx].flags |= P_WAS_SET;
 
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+    if (!starting && errmsg == NULL)
+    {
+	char_u buf_old[11], buf_new[11], buf_type[7];
+	snprintf((char *)buf_old, 10, "%ld", old_value);
+	snprintf((char *)buf_new, 10, "%ld", value);
+	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);
+	reset_v_option_vars();
+    }
+#endif
+
     comp_col();			    /* in case 'columns' or 'ls' changed */
     if (curwin->w_curswant != MAXCOL
 		     && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -133,6 +133,7 @@ void write_viminfo_varlist __ARGS((FILE 
 int store_session_globals __ARGS((FILE *fd));
 void last_set_msg __ARGS((scid_T scriptID));
 void ex_oldfiles __ARGS((exarg_T *eap));
+void reset_v_option_vars __ARGS((void));
 int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
 char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
 /* vim: set ft=c : */
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -38,6 +38,7 @@ SCRIPTS = test1.out test3.out test4.out 
 		test104.out test105.out test106.out test107.out \
 		test_argument_0count.out \
 		test_argument_count.out \
+		test_autocmd_option.out \
 		test_autoformat_join.out \
 		test_breakindent.out \
 		test_changelist.out \
@@ -188,6 +189,7 @@ test106.out: test106.in
 test107.out: test107.in
 test_argument_0count.out: test_argument_0count.in
 test_argument_count.out: test_argument_count.in
+test_autocmd_option.out: test_autocmd_option.in
 test_autoformat_join.out: test_autoformat_join.in
 test_breakindent.out: test_breakindent.in
 test_changelist.out: test_changelist.in
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -37,6 +37,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test105.out test106.out  test107.out\
 		test_argument_0count.out \
 		test_argument_count.out \
+		test_autocmd_option.out \
 		test_autoformat_join.out \
 		test_breakindent.out \
 		test_changelist.out \
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -59,6 +59,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test105.out test106.out test107.out \
 		test_argument_0count.out \
 		test_argument_count.out \
+		test_autocmd_option.out \
 		test_autoformat_join.out \
 		test_breakindent.out \
 		test_changelist.out \
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -39,6 +39,7 @@ SCRIPTS = test1.out test3.out test4.out 
 		test105.out test106.out test107.out \
 		test_argument_0count.out \
 		test_argument_count.out \
+		test_autocmd_option.out \
 		test_autoformat_join.out \
 		test_breakindent.out \
 		test_changelist.out \
--- a/src/testdir/Make_vms.mms
+++ b/src/testdir/Make_vms.mms
@@ -98,6 +98,7 @@ SCRIPT = test1.out  test2.out  test3.out
 	 test105.out test106.out test107.out \
 	 test_argument_0count.out \
 	 test_argument_count.out \
+	 test_autocmd_option.out \
 	 test_autoformat_join.out \
 	 test_breakindent.out \
 	 test_changelist.out \
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -35,6 +35,7 @@ SCRIPTS = test1.out test2.out test3.out 
 		test104.out test105.out test106.out test107.out \
 		test_argument_0count.out \
 		test_argument_count.out \
+		test_autocmd_option.out \
 		test_autoformat_join.out \
 		test_breakindent.out \
 		test_changelist.out \
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_autocmd_option.in
@@ -0,0 +1,73 @@
+Test for option autocommand
+
+STARTTEST
+:so small.vim
+:if !has("eval") || !has("autocmd") | e! test.ok | w! test.out | qa! | endif
+:fu! AutoCommand(match)
+:	let c=g:testcase
+:       let item=remove(g:options, 0)
+:       let c.=printf("Expected: Name: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
+:       let c.=printf("Autocmd Option: <%s>,", a:match)
+:       let c.=printf(" OldVal: <%s>,", v:option_old)
+:       let c.=printf(" NewVal: <%s>,", v:option_new)
+:       let c.=printf(" Scope: <%s>\n", v:option_type)
+:       call setreg('r', printf("%s\n%s", getreg('r'), c))
+:endfu
+:au OptionSet * :call AutoCommand(expand("<amatch>"))
+:let g:testcase="1: Setting number option\n"
+:let g:options=[['number', 0, 1, 'global']]
+:set nu
+:let g:testcase="2: Setting local number option\n"
+:let g:options=[['number', 1, 0, 'local']]
+:setlocal nonu
+:let g:testcase="3: Setting global number option\n"
+:let g:options=[['number', 1, 0, 'global']]
+:setglobal nonu
+:let g:testcase="4: Setting local autoindent option\n"
+:let g:options=[['autoindent', 0, 1, 'local']]
+:setlocal ai
+:let g:testcase="5: Setting global autoindent option\n"
+:let g:options=[['autoindent', 0, 1, 'global']]
+:setglobal ai
+:let g:testcase="6: Setting global autoindent option\n"
+:let g:options=[['autoindent', 1, 0, 'global']]
+:set ai!
+: Should not print anything, use :noa
+:noa :set nonu
+:let g:testcase="7: Setting several global list and number option\n"
+:let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
+:set list nu
+:noa set nolist nonu
+:let g:testcase="8: Setting global acd\n"
+:let g:options=[['autochdir', 0, 1, 'global']]
+:setlocal acd
+:let g:testcase="9: Setting global autoread\n"
+:let g:options=[['autoread', 0, 1, 'global']]
+:set ar
+:let g:testcase="10: Setting local autoread\n"
+:let g:options=[['autoread', 0, 1, 'local']]
+:setlocal ar
+:let g:testcase="11: Setting global autoread\n"
+:let g:options=[['autoread', 1, 0, 'global']]
+:setglobal invar
+:let g:testcase="12: Setting option backspace through :let\n"
+:let g:options=[['backspace', '', 'eol,indent,start', 'global']]
+:let &bs="eol,indent,start"
+:let g:testcase="13: Setting option backspace through setbufvar()\n"
+:let g:options=[['backup', '', '1', 'local']]
+: "try twice, first time, shouldn't trigger because option name is invalid, second time, it should trigger
+:call setbufvar(1, '&l:bk', 1)
+: "should trigger, use correct option name
+:call setbufvar(1, '&backup', 1)
+:" Write register now, because next test shouldn't output anything.
+:$put r
+:let @r=''
+:let g:testcase="\n14: Setting key option, shouldn't trigger\n"
+:let g:options=[['key', 'invalid', 'invalid1', 'invalid']]
+:setlocal key=blah
+:setlocal key=
+:$put =g:testcase
+:%w! test.out
+:qa!
+ENDTEST
+dummy text
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_autocmd_option.ok
@@ -0,0 +1,131 @@
+Test for option autocommand
+
+STARTTEST
+:so small.vim
+:if !has("eval") || !has("autocmd") | e! test.ok | w! test.out | qa! | endif
+:fu! AutoCommand(match)
+:	let c=g:testcase
+:       let item=remove(g:options, 0)
+:       let c.=printf("Expected: Name: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
+:       let c.=printf("Autocmd Option: <%s>,", a:match)
+:       let c.=printf(" OldVal: <%s>,", v:option_old)
+:       let c.=printf(" NewVal: <%s>,", v:option_new)
+:       let c.=printf(" Scope: <%s>\n", v:option_type)
+:       call setreg('r', printf("%s\n%s", getreg('r'), c))
+:endfu
+:au OptionSet * :call AutoCommand(expand("<amatch>"))
+:let g:testcase="1: Setting number option\n"
+:let g:options=[['number', 0, 1, 'global']]
+:set nu
+:let g:testcase="2: Setting local number option\n"
+:let g:options=[['number', 1, 0, 'local']]
+:setlocal nonu
+:let g:testcase="3: Setting global number option\n"
+:let g:options=[['number', 1, 0, 'global']]
+:setglobal nonu
+:let g:testcase="4: Setting local autoindent option\n"
+:let g:options=[['autoindent', 0, 1, 'local']]
+:setlocal ai
+:let g:testcase="5: Setting global autoindent option\n"
+:let g:options=[['autoindent', 0, 1, 'global']]
+:setglobal ai
+:let g:testcase="6: Setting global autoindent option\n"
+:let g:options=[['autoindent', 1, 0, 'global']]
+:set ai!
+: Should not print anything, use :noa
+:noa :set nonu
+:let g:testcase="7: Setting several global list and number option\n"
+:let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
+:set list nu
+:noa set nolist nonu
+:let g:testcase="8: Setting global acd\n"
+:let g:options=[['autochdir', 0, 1, 'global']]
+:setlocal acd
+:let g:testcase="9: Setting global autoread\n"
+:let g:options=[['autoread', 0, 1, 'global']]
+:set ar
+:let g:testcase="10: Setting local autoread\n"
+:let g:options=[['autoread', 0, 1, 'local']]
+:setlocal ar
+:let g:testcase="11: Setting global autoread\n"
+:let g:options=[['autoread', 1, 0, 'global']]
+:setglobal invar
+:let g:testcase="12: Setting option backspace through :let\n"
+:let g:options=[['backspace', '', 'eol,indent,start', 'global']]
+:let &bs="eol,indent,start"
+:let g:testcase="13: Setting option backspace through setbufvar()\n"
+:let g:options=[['backup', '', '1', 'local']]
+: "try twice, first time, shouldn't trigger because option name is invalid, second time, it should trigger
+:call setbufvar(1, '&l:bk', 1)
+: "should trigger, use correct option name
+:call setbufvar(1, '&backup', 1)
+:" Write register now, because next test shouldn't output anything.
+:$put r
+:let @r=''
+:let g:testcase="\n14: Setting key option, shouldn't trigger\n"
+:let g:options=[['key', 'invalid', 'invalid1', 'invalid']]
+:setlocal key=blah
+:setlocal key=
+:$put =g:testcase
+:%w! test.out
+:qa!
+ENDTEST
+dummy text
+
+1: Setting number option
+Expected: Name: <number>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <number>, OldVal: <0>, NewVal: <1>, Scope: <global>
+
+2: Setting local number option
+Expected: Name: <number>, Oldval: <1>, NewVal: <0>, Scope: <local>
+Autocmd Option: <number>, OldVal: <1>, NewVal: <0>, Scope: <local>
+
+3: Setting global number option
+Expected: Name: <number>, Oldval: <1>, NewVal: <0>, Scope: <global>
+Autocmd Option: <number>, OldVal: <1>, NewVal: <0>, Scope: <global>
+
+4: Setting local autoindent option
+Expected: Name: <autoindent>, Oldval: <0>, NewVal: <1>, Scope: <local>
+Autocmd Option: <autoindent>, OldVal: <0>, NewVal: <1>, Scope: <local>
+
+5: Setting global autoindent option
+Expected: Name: <autoindent>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <autoindent>, OldVal: <0>, NewVal: <1>, Scope: <global>
+
+6: Setting global autoindent option
+Expected: Name: <autoindent>, Oldval: <1>, NewVal: <0>, Scope: <global>
+Autocmd Option: <autoindent>, OldVal: <1>, NewVal: <0>, Scope: <global>
+
+7: Setting several global list and number option
+Expected: Name: <list>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <list>, OldVal: <0>, NewVal: <1>, Scope: <global>
+
+7: Setting several global list and number option
+Expected: Name: <number>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <number>, OldVal: <0>, NewVal: <1>, Scope: <global>
+
+8: Setting global acd
+Expected: Name: <autochdir>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <autochdir>, OldVal: <0>, NewVal: <1>, Scope: <local>
+
+9: Setting global autoread
+Expected: Name: <autoread>, Oldval: <0>, NewVal: <1>, Scope: <global>
+Autocmd Option: <autoread>, OldVal: <0>, NewVal: <1>, Scope: <global>
+
+10: Setting local autoread
+Expected: Name: <autoread>, Oldval: <0>, NewVal: <1>, Scope: <local>
+Autocmd Option: <autoread>, OldVal: <1>, NewVal: <1>, Scope: <local>
+
+11: Setting global autoread
+Expected: Name: <autoread>, Oldval: <1>, NewVal: <0>, Scope: <global>
+Autocmd Option: <autoread>, OldVal: <1>, NewVal: <0>, Scope: <global>
+
+12: Setting option backspace through :let
+Expected: Name: <backspace>, Oldval: <>, NewVal: <eol,indent,start>, Scope: <global>
+Autocmd Option: <backspace>, OldVal: <>, NewVal: <eol,indent,start>, Scope: <global>
+
+13: Setting option backspace through setbufvar()
+Expected: Name: <backup>, Oldval: <>, NewVal: <1>, Scope: <local>
+Autocmd Option: <backup>, OldVal: <0>, NewVal: <1>, Scope: <local>
+
+14: Setting key option, shouldn't trigger
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    786,
+/**/
     785,
 /**/
     784,
--- a/src/vim.h
+++ b/src/vim.h
@@ -1335,6 +1335,7 @@ enum auto_event
     EVENT_TEXTCHANGED,		/* text was modified */
     EVENT_TEXTCHANGEDI,		/* text was modified in Insert mode*/
     EVENT_CMDUNDEFINED,		/* command undefined */
+    EVENT_OPTIONSET,		/* option was set */
     NUM_EVENTS			/* MUST be the last one */
 };
 
@@ -1898,7 +1899,10 @@ typedef int proftime_T;	    /* dummy for
 #define VV_WINDOWID	56
 #define VV_PROGPATH	57
 #define VV_COMPLETED_ITEM 58
-#define VV_LEN		59	/* number of v: vars */
+#define VV_OPTION_NEW   59
+#define VV_OPTION_OLD   60
+#define VV_OPTION_TYPE  61
+#define VV_LEN		62	/* number of v: vars */
 
 #ifdef FEAT_CLIPBOARD