changeset 26745:dcd1c244e332 v8.2.3901

patch 8.2.3901: Vim9: Cannot set 'cpo' in main .vimrc if using Vim9 script Commit: https://github.com/vim/vim/commit/71eb3ad5790ef3d16369e2fceb040980d75539cf Author: Bram Moolenaar <Bram@vim.org> Date: Sun Dec 26 12:07:30 2021 +0000 patch 8.2.3901: Vim9: Cannot set 'cpo' in main .vimrc if using Vim9 script Problem: Vim9: Cannot set 'cpo' in main .vimrc if using Vim9 script. Solution: Do not restore 'cpo' at the end of the main .vimrc.
author Bram Moolenaar <Bram@vim.org>
date Sun, 26 Dec 2021 13:15:03 +0100
parents 87a61ed592e6
children 57551c0135af
files runtime/doc/options.txt runtime/doc/vim9.txt src/scriptfile.c src/structs.h src/testdir/test_vim9_script.vim src/version.c
diffstat 6 files changed, 68 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2133,8 +2133,18 @@ A jump table for the options with a shor
 	Commas can be added for readability.
 	To avoid problems with flags that are added in the future, use the
 	"+=" and "-=" feature of ":set" |add-option-flags|.
+
 	NOTE: This option is set to the Vi default value when 'compatible' is
 	set and to the Vim default value when 'compatible' is reset.
+
+	NOTE: In a |Vim9| script, when `vim9script` is encountered, the value
+	is saved, 'cpoptions' is set to the Vim default, and the saved value
+	is restored at the end of the script.  Changes to the value of
+	'cpoptions' will be applied to the saved value, but keep in mind that
+	removing a flag that is not present when 'cpoptions' is changed has no
+	effect.  In the |.vimrc| file the value is not restored, thus using
+	`vim9script` in the |.vimrc| file results in using the Vim default.
+
 	NOTE: This option is set to the POSIX default value at startup when
 	the Vi default value would be used and the $VIM_POSIX environment
 	variable exists |posix|.  This means Vim tries to behave like the
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1402,6 +1402,7 @@ One of the effects is that |line-continu
 The original value of 'cpoptions' is restored at the end of the script, while
 flags added or removed in the script are also added to or removed from the
 original value to get the same effect.  The order of flags may change.
+In the |vimrc| file sourced on startup this does not happen.
 
 							*vim9-mix*
 There is one way to use both legacy and Vim9 syntax in one script file: >
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1372,6 +1372,9 @@ do_source(
 	if (ret_sid != NULL)
 	    *ret_sid = current_sctx.sc_sid;
 
+	// Remember the "is_vimrc" flag for when the file is sourced again.
+	si->sn_is_vimrc = is_vimrc;
+
 	// Used to check script variable index is still valid.
 	si->sn_script_seq = current_sctx.sc_seq;
     }
@@ -1471,9 +1474,11 @@ do_source(
 
 #ifdef FEAT_EVAL
 almosttheend:
+    // If "sn_save_cpo" is set that means we encountered "vim9script": restore
+    // 'cpoptions', unless in the main .vimrc file.
     // Get "si" again, "script_items" may have been reallocated.
     si = SCRIPT_ITEM(current_sctx.sc_sid);
-    if (si->sn_save_cpo != NULL)
+    if (si->sn_save_cpo != NULL && si->sn_is_vimrc == DOSO_NONE)
     {
 	if (STRCMP(p_cpo, CPO_VIM) != 0)
 	{
@@ -1503,8 +1508,8 @@ almosttheend:
 		}
 	}
 	set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, OPT_NO_REDRAW);
-	VIM_CLEAR(si->sn_save_cpo);
     }
+    VIM_CLEAR(si->sn_save_cpo);
 
     restore_funccal();
 # ifdef FEAT_PROFILE
--- a/src/structs.h
+++ b/src/structs.h
@@ -1866,6 +1866,7 @@ typedef struct
     int		sn_version;	// :scriptversion
     int		sn_state;	// SN_STATE_ values
     char_u	*sn_save_cpo;	// 'cpo' value when :vim9script found
+    char	sn_is_vimrc;	// .vimrc file, do not restore 'cpo'
 
 # ifdef FEAT_PROFILE
     int		sn_prof_on;	// TRUE when script is/was profiled
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -4270,18 +4270,64 @@ def Test_restoring_cpo()
   delete('Xclose')
   delete('Xdone')
 
-  writefile(['vim9script'], 'XanotherScript')
+  writefile(['vim9script', 'g:cpoval = &cpo'], 'XanotherScript')
   set cpo=aABceFsMny>
   edit XanotherScript
   so %
   assert_equal('aABceFsMny>', &cpo)
+  assert_equal('aABceFs', g:cpoval)
   :1del
+  setline(1, 'let g:cpoval = &cpo')
   w
   so %
   assert_equal('aABceFsMny>', &cpo)
+  assert_equal('aABceFsMny>', g:cpoval)
 
   delete('XanotherScript')
   set cpo&vim
+  unlet g:cpoval
+
+  if has('unix')
+    # 'cpo' is not restored in main vimrc
+    var save_HOME = $HOME
+    $HOME = getcwd() .. '/Xhome'
+    mkdir('Xhome')
+    var lines =<< trim END
+        vim9script
+        writefile(['before: ' .. &cpo], 'Xresult')
+        set cpo+=M
+        writefile(['after: ' .. &cpo], 'Xresult', 'a')
+    END
+    writefile(lines, 'Xhome/.vimrc')
+
+    lines =<< trim END
+        call writefile(['later: ' .. &cpo], 'Xresult', 'a')
+    END
+    writefile(lines, 'Xlegacy')
+
+    lines =<< trim END
+        vim9script
+        call writefile(['vim9: ' .. &cpo], 'Xresult', 'a')
+        qa
+    END
+    writefile(lines, 'Xvim9')
+
+    var cmd = GetVimCommand() .. " -S Xlegacy -S Xvim9"
+    cmd = substitute(cmd, '-u NONE', '', '')
+    exe "silent !" .. cmd
+
+    assert_equal([
+        'before: aABceFs',
+        'after: aABceFsM',
+        'later: aABceFsM',
+        'vim9: aABceFs'], readfile('Xresult'))
+
+    $HOME = save_HOME
+    delete('Xhome', 'rf')
+    delete('Xlegacy')
+    delete('Xvim9')
+    delete('Xresult')
+  endif
 enddef
 
 " Use :function so we can use Check commands
--- a/src/version.c
+++ b/src/version.c
@@ -750,6 +750,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3901,
+/**/
     3900,
 /**/
     3899,