changeset 18380:212284f893d5 v8.1.2184

patch 8.1.2184: option context is not copied when splitting a window Commit: https://github.com/vim/vim/commit/cfb381421f8be7d6cb4e7dac5b827b23467d3e53 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Oct 19 20:18:47 2019 +0200 patch 8.1.2184: option context is not copied when splitting a window Problem: Option context is not copied when splitting a window. (Daniel Hahler) Solution: Copy the option context, so that ":verbose set" works. (closes #5066)
author Bram Moolenaar <Bram@vim.org>
date Sat, 19 Oct 2019 20:30:04 +0200
parents 0588431c7018
children afd24c11369c
files src/option.c src/testdir/test_options.vim src/version.c
diffstat 3 files changed, 134 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/option.c
+++ b/src/option.c
@@ -5641,6 +5641,12 @@ copy_winopt(winopt_T *from, winopt_T *to
 #ifdef FEAT_SIGNS
     to->wo_scl = vim_strsave(from->wo_scl);
 #endif
+
+#ifdef FEAT_EVAL
+    // Copy the script context so that we know where the value was last set.
+    mch_memmove(to->wo_script_ctx, from->wo_script_ctx,
+						    sizeof(to->wo_script_ctx));
+#endif
     check_winopt(to);		/* don't want NULL pointers */
 }
 
@@ -5738,11 +5744,36 @@ clear_winopt(winopt_T *wop UNUSED)
 #endif
 }
 
+#ifdef FEAT_EVAL
+// Index into the options table for a buffer-local option enum.
+static int buf_opt_idx[BV_COUNT];
+# define COPY_OPT_SCTX(buf, bv) buf->b_p_script_ctx[bv] = options[buf_opt_idx[bv]].script_ctx
+
+/*
+ * Initialize buf_opt_idx[] if not done already.
+ */
+    static void
+init_buf_opt_idx(void)
+{
+    static int did_init_buf_opt_idx = FALSE;
+    int i;
+
+    if (did_init_buf_opt_idx)
+	return;
+    did_init_buf_opt_idx = TRUE;
+    for (i = 0; !istermoption_idx(i); i++)
+	if (options[i].indir & PV_BUF)
+	    buf_opt_idx[options[i].indir & PV_MASK] = i;
+}
+#else
+# define COPY_OPT_SCTX(buf, bv)
+#endif
+
 /*
  * Copy global option values to local options for one buffer.
  * Used when creating a new buffer and sometimes when entering a buffer.
  * flags:
- * BCO_ENTER	We will enter the buf buffer.
+ * BCO_ENTER	We will enter the buffer "buf".
  * BCO_ALWAYS	Always copy the options, but only set b_p_initialized when
  *		appropriate.
  * BCO_NOHELP	Don't copy the values to a help buffer.
@@ -5781,12 +5812,16 @@ buf_copy_options(buf_T *buf, int flags)
 
 	if (should_copy || (flags & BCO_ALWAYS))
 	{
-	    /* Don't copy the options specific to a help buffer when
-	     * BCO_NOHELP is given or the options were initialized already
-	     * (jumping back to a help file with CTRL-T or CTRL-O) */
+	    vim_memset(buf->b_p_script_ctx, 0, sizeof(buf->b_p_script_ctx));
+#ifdef FEAT_EVAL
+	    init_buf_opt_idx();
+#endif
+	    // Don't copy the options specific to a help buffer when
+	    // BCO_NOHELP is given or the options were initialized already
+	    // (jumping back to a help file with CTRL-T or CTRL-O)
 	    dont_do_help = ((flags & BCO_NOHELP) && buf->b_help)
 						       || buf->b_p_initialized;
-	    if (dont_do_help)		/* don't free b_p_isk */
+	    if (dont_do_help)		// don't free b_p_isk
 	    {
 		save_p_isk = buf->b_p_isk;
 		buf->b_p_isk = NULL;
@@ -5821,39 +5856,62 @@ buf_copy_options(buf_T *buf, int flags)
 		free_buf_options(buf, FALSE);
 
 	    buf->b_p_ai = p_ai;
+	    COPY_OPT_SCTX(buf, BV_AI);
 	    buf->b_p_ai_nopaste = p_ai_nopaste;
 	    buf->b_p_sw = p_sw;
+	    COPY_OPT_SCTX(buf, BV_SW);
 	    buf->b_p_tw = p_tw;
+	    COPY_OPT_SCTX(buf, BV_TW);
 	    buf->b_p_tw_nopaste = p_tw_nopaste;
 	    buf->b_p_tw_nobin = p_tw_nobin;
 	    buf->b_p_wm = p_wm;
+	    COPY_OPT_SCTX(buf, BV_WM);
 	    buf->b_p_wm_nopaste = p_wm_nopaste;
 	    buf->b_p_wm_nobin = p_wm_nobin;
 	    buf->b_p_bin = p_bin;
+	    COPY_OPT_SCTX(buf, BV_BIN);
 	    buf->b_p_bomb = p_bomb;
+	    COPY_OPT_SCTX(buf, BV_BOMB);
 	    buf->b_p_fixeol = p_fixeol;
+	    COPY_OPT_SCTX(buf, BV_FIXEOL);
 	    buf->b_p_et = p_et;
+	    COPY_OPT_SCTX(buf, BV_ET);
 	    buf->b_p_et_nobin = p_et_nobin;
 	    buf->b_p_et_nopaste = p_et_nopaste;
 	    buf->b_p_ml = p_ml;
+	    COPY_OPT_SCTX(buf, BV_ML);
 	    buf->b_p_ml_nobin = p_ml_nobin;
 	    buf->b_p_inf = p_inf;
-	    buf->b_p_swf = cmdmod.noswapfile ? FALSE : p_swf;
+	    COPY_OPT_SCTX(buf, BV_INF);
+	    if (cmdmod.noswapfile)
+		buf->b_p_swf = FALSE;
+	    else
+	    {
+		buf->b_p_swf = p_swf;
+		COPY_OPT_SCTX(buf, BV_INF);
+	    }
 	    buf->b_p_cpt = vim_strsave(p_cpt);
+	    COPY_OPT_SCTX(buf, BV_CPT);
 #ifdef BACKSLASH_IN_FILENAME
 	    buf->b_p_csl = vim_strsave(p_csl);
+	    COPY_OPT_SCTX(buf, BV_CSL);
 #endif
 #ifdef FEAT_COMPL_FUNC
 	    buf->b_p_cfu = vim_strsave(p_cfu);
+	    COPY_OPT_SCTX(buf, BV_CFU);
 	    buf->b_p_ofu = vim_strsave(p_ofu);
+	    COPY_OPT_SCTX(buf, BV_OFU);
 #endif
 #ifdef FEAT_EVAL
 	    buf->b_p_tfu = vim_strsave(p_tfu);
+	    COPY_OPT_SCTX(buf, BV_TFU);
 #endif
 	    buf->b_p_sts = p_sts;
+	    COPY_OPT_SCTX(buf, BV_STS);
 	    buf->b_p_sts_nopaste = p_sts_nopaste;
 #ifdef FEAT_VARTABS
 	    buf->b_p_vsts = vim_strsave(p_vsts);
+	    COPY_OPT_SCTX(buf, BV_VSTS);
 	    if (p_vsts && p_vsts != empty_option)
 		tabstop_set(p_vsts, &buf->b_p_vsts_array);
 	    else
@@ -5862,71 +5920,99 @@ buf_copy_options(buf_T *buf, int flags)
 				 ? vim_strsave(p_vsts_nopaste) : NULL;
 #endif
 	    buf->b_p_sn = p_sn;
+	    COPY_OPT_SCTX(buf, BV_SN);
 	    buf->b_p_com = vim_strsave(p_com);
+	    COPY_OPT_SCTX(buf, BV_COM);
 #ifdef FEAT_FOLDING
 	    buf->b_p_cms = vim_strsave(p_cms);
+	    COPY_OPT_SCTX(buf, BV_CMS);
 #endif
 	    buf->b_p_fo = vim_strsave(p_fo);
+	    COPY_OPT_SCTX(buf, BV_FO);
 	    buf->b_p_flp = vim_strsave(p_flp);
+	    COPY_OPT_SCTX(buf, BV_FLP);
 	    // NOTE: Valgrind may report a bogus memory leak for 'nrformats'
 	    // when it is set to 8 bytes in defaults.vim.
 	    buf->b_p_nf = vim_strsave(p_nf);
+	    COPY_OPT_SCTX(buf, BV_NF);
 	    buf->b_p_mps = vim_strsave(p_mps);
+	    COPY_OPT_SCTX(buf, BV_MPS);
 #ifdef FEAT_SMARTINDENT
 	    buf->b_p_si = p_si;
+	    COPY_OPT_SCTX(buf, BV_SI);
 #endif
 	    buf->b_p_ci = p_ci;
+	    COPY_OPT_SCTX(buf, BV_CI);
 #ifdef FEAT_CINDENT
 	    buf->b_p_cin = p_cin;
+	    COPY_OPT_SCTX(buf, BV_CIN);
 	    buf->b_p_cink = vim_strsave(p_cink);
+	    COPY_OPT_SCTX(buf, BV_CINK);
 	    buf->b_p_cino = vim_strsave(p_cino);
-#endif
-	    /* Don't copy 'filetype', it must be detected */
+	    COPY_OPT_SCTX(buf, BV_CINO);
+#endif
+	    // Don't copy 'filetype', it must be detected
 	    buf->b_p_ft = empty_option;
 	    buf->b_p_pi = p_pi;
+	    COPY_OPT_SCTX(buf, BV_PI);
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
 	    buf->b_p_cinw = vim_strsave(p_cinw);
+	    COPY_OPT_SCTX(buf, BV_CINW);
 #endif
 #ifdef FEAT_LISP
 	    buf->b_p_lisp = p_lisp;
+	    COPY_OPT_SCTX(buf, BV_LISP);
 #endif
 #ifdef FEAT_SYN_HL
 	    /* Don't copy 'syntax', it must be set */
 	    buf->b_p_syn = empty_option;
 	    buf->b_p_smc = p_smc;
+	    COPY_OPT_SCTX(buf, BV_SMC);
 	    buf->b_s.b_syn_isk = empty_option;
 #endif
 #ifdef FEAT_SPELL
 	    buf->b_s.b_p_spc = vim_strsave(p_spc);
+	    COPY_OPT_SCTX(buf, BV_SPC);
 	    (void)compile_cap_prog(&buf->b_s);
 	    buf->b_s.b_p_spf = vim_strsave(p_spf);
+	    COPY_OPT_SCTX(buf, BV_SPF);
 	    buf->b_s.b_p_spl = vim_strsave(p_spl);
+	    COPY_OPT_SCTX(buf, BV_SPL);
 #endif
 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
 	    buf->b_p_inde = vim_strsave(p_inde);
+	    COPY_OPT_SCTX(buf, BV_INDE);
 	    buf->b_p_indk = vim_strsave(p_indk);
+	    COPY_OPT_SCTX(buf, BV_INDK);
 #endif
 	    buf->b_p_fp = empty_option;
 #if defined(FEAT_EVAL)
 	    buf->b_p_fex = vim_strsave(p_fex);
+	    COPY_OPT_SCTX(buf, BV_FEX);
 #endif
 #ifdef FEAT_CRYPT
 	    buf->b_p_key = vim_strsave(p_key);
+	    COPY_OPT_SCTX(buf, BV_KEY);
 #endif
 #ifdef FEAT_SEARCHPATH
 	    buf->b_p_sua = vim_strsave(p_sua);
+	    COPY_OPT_SCTX(buf, BV_SUA);
 #endif
 #ifdef FEAT_KEYMAP
 	    buf->b_p_keymap = vim_strsave(p_keymap);
+	    COPY_OPT_SCTX(buf, BV_KMAP);
 	    buf->b_kmap_state |= KEYMAP_INIT;
 #endif
 #ifdef FEAT_TERMINAL
 	    buf->b_p_twsl = p_twsl;
+	    COPY_OPT_SCTX(buf, BV_TWSL);
 #endif
 	    /* This isn't really an option, but copying the langmap and IME
 	     * state from the current buffer is better than resetting it. */
 	    buf->b_p_iminsert = p_iminsert;
+	    COPY_OPT_SCTX(buf, BV_IMI);
 	    buf->b_p_imsearch = p_imsearch;
+	    COPY_OPT_SCTX(buf, BV_IMS);
 
 	    /* options that are normally global but also have a local value
 	     * are not copied, start using the global value */
@@ -5950,12 +6036,14 @@ buf_copy_options(buf_T *buf, int flags)
 	    buf->b_p_inc = empty_option;
 # ifdef FEAT_EVAL
 	    buf->b_p_inex = vim_strsave(p_inex);
+	    COPY_OPT_SCTX(buf, BV_INEX);
 # endif
 #endif
 	    buf->b_p_dict = empty_option;
 	    buf->b_p_tsr = empty_option;
 #ifdef FEAT_TEXTOBJ
 	    buf->b_p_qe = vim_strsave(p_qe);
+	    COPY_OPT_SCTX(buf, BV_QE);
 #endif
 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
 	    buf->b_p_bexpr = empty_option;
@@ -5965,6 +6053,7 @@ buf_copy_options(buf_T *buf, int flags)
 #endif
 #ifdef FEAT_PERSISTENT_UNDO
 	    buf->b_p_udf = p_udf;
+	    COPY_OPT_SCTX(buf, BV_UDF);
 #endif
 #ifdef FEAT_LISP
 	    buf->b_p_lw = empty_option;
@@ -5990,10 +6079,12 @@ buf_copy_options(buf_T *buf, int flags)
 	    else
 	    {
 		buf->b_p_isk = vim_strsave(p_isk);
+		COPY_OPT_SCTX(buf, BV_ISK);
 		did_isk = TRUE;
 		buf->b_p_ts = p_ts;
 #ifdef FEAT_VARTABS
 		buf->b_p_vts = vim_strsave(p_vts);
+		COPY_OPT_SCTX(buf, BV_VTS);
 		if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
 		    tabstop_set(p_vts, &buf->b_p_vts_array);
 		else
@@ -6003,6 +6094,7 @@ buf_copy_options(buf_T *buf, int flags)
 		if (buf->b_p_bt[0] == 'h')
 		    clear_string_option(&buf->b_p_bt);
 		buf->b_p_ma = p_ma;
+		COPY_OPT_SCTX(buf, BV_MA);
 	    }
 	}
 
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -296,20 +296,48 @@ func Test_set_errors()
   call assert_fails('set t_foo=', 'E846:')
 endfunc
 
+func CheckWasSet(name)
+  let verb_cm = execute('verbose set ' .. a:name .. '?')
+  call assert_match('Last set from.*test_options.vim', verb_cm)
+endfunc
+func CheckWasNotSet(name)
+  let verb_cm = execute('verbose set ' .. a:name .. '?')
+  call assert_notmatch('Last set from', verb_cm)
+endfunc
+
 " Must be executed before other tests that set 'term'.
 func Test_000_term_option_verbose()
   CheckNotGui
 
-  let verb_cm = execute('verbose set t_cm')
-  call assert_notmatch('Last set from', verb_cm)
+  call CheckWasNotSet('t_cm')
 
   let term_save = &term
   set term=ansi
-  let verb_cm = execute('verbose set t_cm')
-  call assert_match('Last set from.*test_options.vim', verb_cm)
+  call CheckWasSet('t_cm')
   let &term = term_save
 endfunc
 
+func Test_copy_context()
+  setlocal list
+  call CheckWasSet('list')
+  split
+  call CheckWasSet('list')
+  quit
+  setlocal nolist
+
+  set ai
+  call CheckWasSet('ai')
+  set filetype=perl
+  call CheckWasSet('filetype')
+  set fo=tcroq
+  call CheckWasSet('fo')
+
+  split Xsomebuf
+  call CheckWasSet('ai')
+  call CheckWasNotSet('filetype')
+  call CheckWasSet('fo')
+endfunc
+
 func Test_set_ttytype()
   CheckUnix
   CheckNotGui
--- 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 */
 /**/
+    2184,
+/**/
     2183,
 /**/
     2182,