From d7b7922dcb41cb435af408440322e4382532aad2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Jul 2026 08:38:40 +0800 Subject: [PATCH 1/2] vim-patch:partial:9.2.0579: :mksession, :mkview and :mkvimrc emit legacy Vim script https://github.com/vim/vim/commit/d69cf0dbcfdd721d94189ffa1558660c96129627 New tests only. Co-authored-by: Miguel Barro Co-authored-by: Christian Brabandt --- test/old/testdir/test_autocmd.vim | 2 +- test/old/testdir/test_mksession.vim | 266 ++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 1 deletion(-) diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index 4c3055eaaa..2042c8284f 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -1203,10 +1203,10 @@ endfunc " Closing a window might cause an endless loop " E814 for older Vims func Test_autocmd_bufwipe_in_SessLoadPost() + set noswapfile edit Xtest tabnew file Xsomething - set noswapfile mksession! let content =<< trim [CODE] diff --git a/test/old/testdir/test_mksession.vim b/test/old/testdir/test_mksession.vim index 135a1216fb..dbb0a1b9af 100644 --- a/test/old/testdir/test_mksession.vim +++ b/test/old/testdir/test_mksession.vim @@ -1280,4 +1280,270 @@ func Test_mkview_default_home() endif endfunc +" Test vim9 expression mappings +func Test_mksession_vim9_expr_mappings() + throw 'Skipped: Vim9 script is N/A' + CheckFeature packages + + " Create a dummy vim9 plugin + const base = getcwd() . '/rtdir' + const root = base . '/pack/test/opt/dummy9' + call mkdir(root . '/plugin', 'p') + let plugin_sources =<< trim END + vim9script + import autoload 'dummy9.vim' + nnoremap dummy-test dummy9.Test() .. "" + END + call writefile(plugin_sources, root . '/plugin/dummy9.vim') + + call mkdir(root . '/autoload', 'p') + let auto_sources =<< trim END + vim9script + const ref_txt = 'Hello from vim9 dummy plugin!' + export def Test(): string + writefile([ref_txt], 'XDummyOutput') + return has("gui_running") ? '' : $':echomsg "{ref_txt}"' + enddef + END + call writefile(auto_sources, root . '/autoload/dummy9.vim') + + " clean up later + defer delete(base, 'rf') + + " Load and check the plugin + const ref_txt = 'Hello from vim9 dummy plugin!' + let &packpath .= ',' . base + packadd dummy9 + messages clear + normal dummy-test + + if !has('gui_running') + call assert_match(ref_txt, execute('messages'), 'No vim9 plugin dummy.Test() execution') + endif + call assert_true(filereadable('XDummyOutput'), 'Output file was not created by Vim9 plugin') + call assert_equal([ref_txt], readfile('XDummyOutput')) + call delete('XDummyOutput') + + " Create a session file + mksession! XDummySession.vim + defer delete('XDummySession.vim') + call assert_true(filereadable('XDummySession.vim'), 'Session file was not created') + + " Check the session file mappings are operational + let test_sources =<< trim END + " load session + source XDummySession.vim + " execute vim9 expression mapping + normal dummy-test + " on my way + cq + END + call writefile(test_sources, 'XTest.vim', 'D') + " spawn a new Vim instance to load the session and execute the mapping + call system(GetVimCommand('XTest.vim')) + defer delete('XDummyOutput') + call assert_true(filereadable('XDummyOutput'), + \ 'Expected output file was not created by Vim9 plugin') + call assert_equal([ref_txt], readfile('XDummyOutput')) + +endfunc + +" Test legacy vimscript expression mappings +func Test_mksession_legacy_expr_mappings() + + CheckFeature packages + + " Create a dummy vim9 plugin + const base = getcwd() . '/rtdir' + const root = base . '/pack/test/opt/dummy' + call mkdir(root . '/plugin', 'p') + + " clean up later + defer delete(base, 'rf') + + let plugin_sources =<< trim END + nnoremap dummy-test dummy#Test() . "" + END + call writefile(plugin_sources, root . '/plugin/dummy.vim') + + call mkdir(root . '/autoload', 'p') + let auto_sources =<< trim END + const s:ref_txt = 'Hello from good old dummy plugin!' + func dummy#Test() + call writefile([s:ref_txt], 'XDummyOutput') + return has("gui_running") ? '' : $':echomsg "{s:ref_txt}"' + endfunc + END + call writefile(auto_sources, root . '/autoload/dummy.vim') + + " Load and check the plugin + const ref_txt = 'Hello from good old dummy plugin!' + let &packpath .= ',' . base + packadd dummy + messages clear + normal dummy-test + + if !has("gui_running") + call assert_match(ref_txt, execute('messages'), 'No vim9 plugin dummy.Test() execution') + endif + call assert_true(filereadable('XDummyOutput'), 'Output file was not created by legacy plugin') + call assert_equal([ref_txt], readfile('XDummyOutput')) + call delete('XDummyOutput') + + " Create a session file + mksession! XDummySession.vim + defer delete('XDummySession.vim') + call assert_true(filereadable('XDummySession.vim'), 'Session file was not created') + + " Check the session file mappings are operational + let test_sources =<< trim END + " load session + source XDummySession.vim + " execute legacy vimscript expression mapping + normal dummy-test + " on my way + cq + END + call writefile(test_sources, 'XTest.vim', 'D') + " spawn a new Vim instance to load the session and execute the mapping + call system(GetVimCommand('XTest.vim')) + defer delete('XDummyOutput') + call assert_true(filereadable('XDummyOutput'), + \ 'Expected output file was not created by legacy vim plugin') + call assert_equal([ref_txt], readfile('XDummyOutput')) + +endfunc + +" Test sessions cursor position management +func Test_mksession_cursor_position() + + " Set windows test scenario + let files = [] + for i in range(10) + let file = $'Xfile{i}' + exe $"{i ? 'split' : 'edit'} {file}" + call append(0, $"Session file cursor position testing {i}") + " Force cursor position restoring commands + setlocal nowrap + normal dd29zl + " Check expected position + call assert_equal([0, 1, 30, 0], getpos('.'), $"Fail to set cursor position for {file}") + write! + let files += [file] + endfor + + " Save session + mksession! Xtest_curpos + + " Test restoring session + %bwipe! + try + source Xtest_curpos + catch + call assert_report("Failure sourcing session file") + endtry + + " Check cursor position + for file in files + exe $"drop {file}" + call assert_equal([0, 1, 30, 0], getpos('.'), $"Cursor position not restored correctly for {file}") + endfor + + " Clean up + call delete('Xtest_curpos') + for file in files + call delete(file) + endfor +endfunc + +" Test sessions global and local mappings +func Test_mksession_localmappings() + + " Create sessions. Mapping execution is tested running a file + let valid_sessions = [] " keep map info + let invalid_sessions = [] " do not keep map info + " localoptions requires a buffer + setlocal noswapfile + silent write XDummy + defer delete('XDummy') + + " Nvim: default 'sessionoptions' doesn't include "options" + "for option in ["&", "=options", "=localoptions"] + for option in ["=options", "=localoptions"] + for global in [0, 1] + + " select options + exe "set sessionoptions" .. option + + " mapping + exe "nnoremap" . (global ? " " : " ") + \ . "dummy-test silent write XDummyOutput" + let case = $"mapping_{global ? "global" : "local"}_{option}" + + " test mapping + normal dummy-test + call assert_true(filereadable("XDummyOutput"), $"Output file was not created by {case}") + call delete("XDummyOutput") + + " session + let sessionfile = "XSession_" . case + exe $"mksession {sessionfile}" + + if global && option =~ "localoptions" + let invalid_sessions += [sessionfile] + else + let valid_sessions += [sessionfile] + endif + + " clear mappings + nmapclear + nmapclear + + endfor + endfor + + " Check the session files are operational + for session in valid_sessions + + let test_sources =<< trim eval END + " load session + silent source {session} + " execute legacy vimscript expression mapping + normal dummy-test + " on my way + cq + END + + call writefile(test_sources, 'XTest.vim') + call system(GetVimCommand('XTest.vim')) + call assert_true(filereadable('XDummyOutput'), + \ $"Expected map not defined in session file {session}") + call delete('XDummyOutput') + call delete(session) + + endfor + + for session in invalid_sessions + + let test_sources =<< trim eval END + " load session + silent source {session} + " execute legacy vimscript expression mapping + normal dummy-test + " on my way + cq + END + + call writefile(test_sources, 'XTest.vim') + call system(GetVimCommand('XTest.vim')) + call assert_false(filereadable('XDummyOutput'), + \ $"Unexpected map defined in session file {session}") + if filereadable('XDummyOutput') + call delete('XDummyOutput') + endif + call delete(session) + endfor + +endfunc + " vim: shiftwidth=2 sts=2 expandtab From 60e46704bd793e52b7f62278719d4f92746c3d78 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Jul 2026 08:32:38 +0800 Subject: [PATCH 2/2] vim-patch:9.2.0782: tests: missing cleanup in test_mksession.vim Problem: Some test_mksession tests do not cleanup all the state Solution: Add commands to clean up state introduced by the test (Illia Bobyr) Before this change the following 4 tests were failing when executed individually: Test_mksession_arglocal_localdir Test_mksession_buffer_count Test_mksession_one_buffer_two_windows Test_mksession_winminheight As in ``` TEST_FILTER=winminheight make test_mksession ``` Yet, when ran as part of the whole test suite they succeeded. This was due to some state leaking from one test into another. I think this is bad, as it can confuse someone making changes in the relevant area. `Test_mksession_winminheight` is actually still broken a bit, and requires `winheight` and `winwidth` set at the beginning of the test, rather than later, when it actually matters. This exposes a subtle bug in the session restore script. I have a patch in a separate commit. closes: vim/vim#20691 https://github.com/vim/vim/commit/834b8d218f1db92e587ecd449e5ce88b41fbe256 Co-authored-by: Illia Bobyr --- test/old/testdir/test_mksession.vim | 79 ++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/test/old/testdir/test_mksession.vim b/test/old/testdir/test_mksession.vim index dbb0a1b9af..00a9de672b 100644 --- a/test/old/testdir/test_mksession.vim +++ b/test/old/testdir/test_mksession.vim @@ -32,6 +32,9 @@ func Test__mksession_arglocal() endfunc func Test_mksession_arglocal_localdir() + argglobal + %argdelete + call mkdir('Xa', 'R') call writefile(['This is Xb'], 'Xa/Xb.txt', 'D') let olddir = getcwd() @@ -71,6 +74,7 @@ func Test_mksession() tabnew let wrap_save = &wrap set sessionoptions=buffers splitbelow fileencoding=latin1 + defer execute('set sessionoptions& splitbelow&') call setline(1, [ \ 'start:', \ 'no multibyte chAracter', @@ -163,13 +167,14 @@ func Test_mksession() call delete('Xtest_mks.out') call delete(tmpfile) let &wrap = wrap_save - set sessionoptions& endfunc func Test_mksession_winheight() new set winheight=10 + defer execute('set winheight&') set winminheight=2 + defer execute('set winminheight&') mksession! Xtest_mks.out source Xtest_mks.out @@ -178,6 +183,7 @@ endfunc func Test_mksession_large_winheight() set winheight=999 + defer execute('set winheight&') mksession! Xtest_mks_winheight.out set winheight& source Xtest_mks_winheight.out @@ -186,6 +192,7 @@ endfunc func Test_mksession_zero_winheight() set winminheight=0 + defer execute('set winminheight&') edit SomeFile split wincmd _ @@ -243,6 +250,9 @@ func Test_mksession_arglist() endfunc func Test_mksession_one_buffer_two_windows() + set splitbelow + defer execute('set splitbelow&') + edit Xtest1 new Xtest2 split @@ -351,6 +361,9 @@ func Test_mksession_blank_tabs() endfunc func Test_mksession_buffer_count() + argglobal + %argdelete + set hidden " Edit exactly three files in the current session. @@ -996,9 +1009,13 @@ endfunc " Test for mksession without options restores winminheight func Test_mksession_winminheight() + set winheight=10 winwidth=10 winminheight& winminwidth& + defer execute('set winheight& winwidth&') set sessionoptions-=options + defer execute('set sessionoptions&') split mksession! Xtest_mks.out + defer delete('Xtest_mks.out') let found_restore = 0 let lines = readfile('Xtest_mks.out') for line in lines @@ -1014,12 +1031,11 @@ func Test_mksession_winminheight() tabclose | tabclose | close call assert_equal(1, tabpagenr('$')) set winminheight=2 winminwidth=2 + defer execute('set winminheight& winminwidth&') source Xtest_mks.out call assert_equal(3, tabpagenr('$')) call assert_equal([2, 2], [&winminheight, &winminwidth]) tabclose | tabclose | close - call delete('Xtest_mks.out') - set sessionoptions& winminheight& winminwidth& endfunc " Test for mksession with and without options restores shortmess @@ -1312,8 +1328,12 @@ func Test_mksession_vim9_expr_mappings() " Load and check the plugin const ref_txt = 'Hello from vim9 dummy plugin!' + let orig_packpath = &packpath let &packpath .= ',' . base + let orig_runtimepath = &runtimepath packadd dummy9 + defer execute('let &packpath = orig_runtimepath') + defer execute('let &runtimepath = orig_runtimepath') messages clear normal dummy-test @@ -1378,8 +1398,12 @@ func Test_mksession_legacy_expr_mappings() " Load and check the plugin const ref_txt = 'Hello from good old dummy plugin!' + let orig_packpath = &packpath let &packpath .= ',' . base + let orig_runtimepath = &runtimepath packadd dummy + defer execute('let &packpath = orig_runtimepath') + defer execute('let &runtimepath = orig_runtimepath') messages clear normal dummy-test @@ -1454,6 +1478,8 @@ func Test_mksession_cursor_position() for file in files call delete(file) endfor + + %bwipe endfunc " Test sessions global and local mappings @@ -1472,32 +1498,37 @@ func Test_mksession_localmappings() for option in ["=options", "=localoptions"] for global in [0, 1] - " select options - exe "set sessionoptions" .. option + try + " select options + exe "set sessionoptions" .. option - " mapping - exe "nnoremap" . (global ? " " : " ") - \ . "dummy-test silent write XDummyOutput" - let case = $"mapping_{global ? "global" : "local"}_{option}" + " mapping + exe "nnoremap" . (global ? " " : " ") + \ . "dummy-test silent write XDummyOutput" + let case = $"mapping_{global ? "global" : "local"}_{option}" - " test mapping - normal dummy-test - call assert_true(filereadable("XDummyOutput"), $"Output file was not created by {case}") - call delete("XDummyOutput") + " test mapping + normal dummy-test + call assert_true(filereadable("XDummyOutput"), $"Output file was not created by {case}") - " session - let sessionfile = "XSession_" . case - exe $"mksession {sessionfile}" + " session + let sessionfile = "XSession_" . case + exe $"mksession {sessionfile}" - if global && option =~ "localoptions" - let invalid_sessions += [sessionfile] - else - let valid_sessions += [sessionfile] - endif + if global && option =~ "localoptions" + let invalid_sessions += [sessionfile] + else + let valid_sessions += [sessionfile] + endif - " clear mappings - nmapclear - nmapclear + finally + call delete("XDummyOutput") + + " clear mappings + nmapclear + nmapclear + set sessionoptions& + endtry endfor endfor