commit 813a6d3b1128fa8bc54fcc7e0468991bee47d11f parent 138922497fc76d9d0a561981a25c0648fdfce7ae Author: zeertzjq <zeertzjq@outlook.com> Date: Sat, 24 Jan 2026 10:25:05 +0800 Merge pull request #37530 from zeertzjq/vim-9.1.1908 vim-patch:8.2.4738,9.0.{0874,1066,1480},9.1.{1370,1908} Diffstat:
30 files changed, 253 insertions(+), 28 deletions(-)
diff --git a/src/nvim/errors.h b/src/nvim/errors.h @@ -195,6 +195,8 @@ EXTERN const char e_stray_closing_curly_str[] INIT(= N_("E1278: Stray '}' without a matching '{': %s")); EXTERN const char e_missing_close_curly_str[] INIT(= N_("E1279: Missing '}': %s")); +EXTERN const char e_cannot_change_menus_while_listing[] +INIT(= N_("E1310: Cannot change menus while listing")); EXTERN const char e_not_allowed_to_change_window_layout_in_this_autocmd[] INIT(= N_("E1312: Not allowed to change the window layout in this autocmd")); diff --git a/src/nvim/menu.c b/src/nvim/menu.c @@ -48,6 +48,10 @@ #include "menu.c.generated.h" +/// When non-zero no menu must be added or cleared. Prevents the list of menus +/// changing while listing them. +static int menus_locked = 0; + /// The character for each menu mode static char *menu_mode_chars[] = { "n", "v", "s", "o", "i", "c", "tl", "t" }; @@ -67,6 +71,17 @@ static vimmenu_T **get_root_menu(const char *const name) return &root_menu; } +/// If "menus_locked" is set then give an error and return true. +/// Otherwise return false. +static int is_menus_locked(void) +{ + if (menus_locked > 0) { + emsg(_(e_cannot_change_menus_while_listing)); + return true; + } + return false; +} + /// Do the :menu command and relatives. /// @param eap Ex command arguments void ex_menu(exarg_T *eap) @@ -202,6 +217,10 @@ void ex_menu(exarg_T *eap) } menu_enable_recurse(*root_menu_ptr, menu_path, modes, enable); } else if (unmenu) { + if (is_menus_locked()) { + goto theend; + } + // Delete menu(s). if (strcmp(menu_path, "*") == 0) { // meaning: remove all menus menu_path = ""; @@ -221,6 +240,10 @@ void ex_menu(exarg_T *eap) // Careful: remove_menu() changes menu_path remove_menu(root_menu_ptr, menu_path, modes, false); } else { + if (is_menus_locked()) { + goto theend; + } + // Add menu(s). // Replace special key codes. if (STRICMP(map_to, "<nop>") == 0) { // "<Nop>" means nothing @@ -729,12 +752,14 @@ bool menu_get(char *const path_name, int modes, list_T *list) /// Find menu matching `name` and `modes`. Does not handle empty `name`. /// -/// @param menu top menu to start looking from -/// @param name path towards the menu +/// @param menu top menu to start looking from +/// @param path_name path towards the menu /// @return found menu or NULL -static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes) +static vimmenu_T *find_menu(vimmenu_T *menu, const char *path_name, int modes) { - assert(*name); + assert(*path_name); + char *const saved_name = xstrdup(path_name); + char *name = saved_name; while (*name) { // find the end of one dot-separated name and put a NUL at the dot @@ -744,12 +769,14 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes) // Found menu if (*p != NUL && menu->children == NULL) { emsg(_(e_notsubmenu)); - return NULL; + menu = NULL; + goto theend; } else if ((menu->modes & modes) == 0x0) { emsg(_(e_menu_only_exists_in_another_mode)); - return NULL; + menu = NULL; + goto theend; } else if (*p == NUL) { // found a full match - return menu; + goto theend; } break; } @@ -758,7 +785,7 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes) if (menu == NULL) { semsg(_(e_nomenu), name); - return NULL; + break; } // Found a match, search the sub-menu. name = p; @@ -766,7 +793,9 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes) menu = menu->children; } - abort(); +theend: + xfree(saved_name); + return menu; } /// Show the mapping associated with a menu item or hierarchy in a sub-menu. @@ -781,10 +810,14 @@ static int show_menus(char *const path_name, int modes) } } - // Now we have found the matching menu, and we list the mappings. + // make sure the list of menus doesn't change while listing them + menus_locked++; + + // list the matching menu mappings msg_puts_title(_("\n--- Menus ---")); show_menus_recursive(menu, modes, 0); + menus_locked--; return OK; } diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua @@ -326,6 +326,37 @@ describe('cmdline', function() ]]) end) + -- oldtest: Test_wildmenu_with_pum_foldexpr() + it('pum when using &foldtext', function() + local screen = Screen.new(60, 10) + exec([[ + call setline(1, ['folded one', 'folded two', 'some more text']) + func MyFoldText() + return 'foo' + endfunc + set foldtext=MyFoldText() wildoptions=pum + normal ggzfj + ]]) + feed(':set<Tab>') + screen:expect([[ + {13:foo·························································}| + some more text | + {1:~ }|*3 + {12: set }{1: }| + {4: setfiletype }{1: }| + {4: setglobal }{1: }| + {4: setlocal }{1: }| + :set^ | + ]]) + feed('<Esc>') + screen:expect([[ + {13:^foo·························································}| + some more text | + {1:~ }|*7 + | + ]]) + end) + -- oldtest: Test_rulerformat_position() it("ruler has correct position with 'rulerformat' set", function() local screen = Screen.new(20, 3) diff --git a/test/old/testdir/check.vim b/test/old/testdir/check.vim @@ -124,13 +124,39 @@ func CheckNotMacM1() endif endfunc +func SetupWindowSizeToForVisualDumps() + " The dumps used as reference in these tests were created with a terminal + " width of 75 columns. The vim window that uses the remainder of the GUI + " window width must be at least 3 columns. In theory this means we need the + " GUI shell to provide 78+ columns. However the GTK3 resize logic is flaky, + " sometimes resulting in X11 Configure events that are narrower than + " expected by a number of pixels equal to 2 column widths. Therefore + " setting 80 columns ensures that the GUI shell can still provide 78+ + " columns. This is very likely papering over a GTK3 resize bug but one that + " has existed for a very long time. Establishing this workaround is meant to + " get the GTK3 code working under CI so that we can focus on removing this + " over the long term. + if &columns != 80 + set columns=80 + endif + " Without resetting lines, some GTK3 resize events can carry over between + " tests, which invalidate assumptions in the scrollbar offset calculations. + if &lines != 25 + set lines=25 + endif +endfunc + " Command to check that making screendumps is supported. " Caller must source screendump.vim command CheckScreendump call CheckScreendump() func CheckScreendump() + let g:check_screendump_called = v:true if !CanRunVimInTerminal() throw 'Skipped: cannot make screendumps' endif + if has('gui_running') + call SetupWindowSizeToForVisualDumps() + endif endfunc " Command to check that we can Run Vim in a terminal window diff --git a/test/old/testdir/runtest.vim b/test/old/testdir/runtest.vim @@ -643,6 +643,8 @@ for g:testfunc in sort(s:tests) " A test can set g:test_is_flaky to retry running the test. let g:test_is_flaky = 0 + let g:check_screendump_called = v:false + " A test can set g:max_run_nr to change the max retry count. let g:max_run_nr = 5 if has('mac') diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim @@ -580,6 +580,7 @@ func Test_WinScrolled_close_curwin() endfunc func Test_WinScrolled_once_only() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -609,6 +610,7 @@ endfunc " Check that WinScrolled is not triggered immediately when defined and there " are split windows. func Test_WinScrolled_not_when_defined() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -3015,6 +3017,7 @@ endfunc func Test_autocmd_nested_switch_window() " run this in a separate Vim so that SafeState works CheckRunVimInTerminal + CheckScreendump let lines =<< trim END vim9script diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim @@ -2849,6 +2849,7 @@ endfunc " Test for using a popup menu for the command line completion matches " (wildoptions=pum) func Test_wildmenu_pum() + CheckScreendump CheckRunVimInTerminal let commands =<< trim [CODE] @@ -3201,10 +3202,35 @@ func Test_wildmenumode_with_pum() cunmap <F2> endfunc +func Test_wildmenu_with_pum_foldexpr() + CheckScreendump + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, ['folded one', 'folded two', 'some more text']) + func MyFoldText() + return 'foo' + endfunc + set foldtext=MyFoldText() wildoptions=pum + normal ggzfj + END + call writefile(lines, 'Xpumfold') + let buf = RunVimInTerminal('-S Xpumfold', #{rows: 10}) + call term_sendkeys(buf, ":set\<Tab>") + call VerifyScreenDump(buf, 'Test_wildmenu_with_pum_foldexpr_1', {}) + + call term_sendkeys(buf, "\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_with_pum_foldexpr_2', {}) + + call StopVimInTerminal(buf) + call delete('Xpumfold') +endfunc + " Test for opening the cmdline completion popup menu from the terminal window. " The popup menu should be positioned correctly over the status line of the " bottom-most window. func Test_wildmenu_pum_from_terminal() + CheckScreendump CheckRunVimInTerminal let python = PythonProg() call CheckPython(python) @@ -3225,6 +3251,7 @@ func Test_wildmenu_pum_from_terminal() endfunc func Test_wildmenu_pum_odd_wildchar() + CheckScreendump CheckRunVimInTerminal " Test odd wildchar interactions with pum. Make sure they behave properly diff --git a/test/old/testdir/test_conceal.vim b/test/old/testdir/test_conceal.vim @@ -563,6 +563,8 @@ endfunc " Test that cursor is drawn at the correct column when it is after end of the " line with 'virtualedit' and concealing. func Run_test_conceal_virtualedit_after_eol(wrap) + CheckScreendump + let code =<< trim eval [CODE] let &wrap = {a:wrap} call setline(1, 'abcdefgh|hidden|ijklmnpop') @@ -595,6 +597,8 @@ endfunc " Same as Run_test_conceal_virtualedit_after_eol(), but with 'rightleft'. func Run_test_conceal_virtualedit_after_eol_rightleft(wrap) + CheckScreendump + let code =<< trim eval [CODE] let &wrap = {a:wrap} call setline(1, 'abcdefgh|hidden|ijklmnpop') @@ -628,6 +632,8 @@ endfunc " Test that cursor position is correct when double-width chars are concealed. func Run_test_conceal_double_width(wrap) + CheckScreendump + let code =<< trim eval [CODE] let &wrap = {a:wrap} call setline(1, ['aaaaa口=口bbbbb口=口ccccc', 'foobar']) diff --git a/test/old/testdir/test_crash.vim b/test/old/testdir/test_crash.vim @@ -7,7 +7,12 @@ CheckScreendump " Run the command in terminal and wait for it to complete via notification func s:RunCommandAndWait(buf, cmd) call term_sendkeys(a:buf, a:cmd .. "; printf '" .. TermNotifyParentCmd(v:false) .. "'\<cr>") - call WaitForChildNotification() + if ValgrindOrAsan() + " test times out on ASAN CI builds + call WaitForChildNotification(10000) + else + call WaitForChildNotification() + endif endfunc func Test_crash1() @@ -241,6 +246,7 @@ func Test_crash1_3() endfunc func Test_crash2() + CheckScreendump " The following used to crash Vim let opts = #{wait_for_ruler: 0, rows: 20} let args = ' -u NONE -i NONE -n -e -s -S ' diff --git a/test/old/testdir/test_cursor_func.vim b/test/old/testdir/test_cursor_func.vim @@ -90,6 +90,10 @@ func Test_curswant_with_cursorline() endfunc func Test_screenpos() + if has('gui_running') + set lines=25 + set columns=78 + endif rightbelow new rightbelow 20vsplit call setline(1, ["\tsome text", "long wrapping line here", "next line"]) diff --git a/test/old/testdir/test_delete.vim b/test/old/testdir/test_delete.vim @@ -111,6 +111,7 @@ endfunc " This should no longer trigger ml_get errors func Test_delete_ml_get_errors() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END set noshowcmd noruler scrolloff=0 diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim @@ -951,6 +951,8 @@ endfunc " Verify a screendump with both the internal and external diff. func VerifyBoth(buf, dumpfile, extra) + CheckScreendump + " trailing : for leaving the cursor on the command line for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"] call term_sendkeys(a:buf, cmd) @@ -970,6 +972,8 @@ endfunc " Verify a screendump with the internal diff only. func VerifyInternal(buf, dumpfile, extra) + CheckScreendump + call term_sendkeys(a:buf, ":diffupdate!\<CR>") " trailing : for leaving the cursor on the command line call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:") diff --git a/test/old/testdir/test_display.vim b/test/old/testdir/test_display.vim @@ -519,6 +519,8 @@ func Test_display_linebreak_breakat() endfunc func Run_Test_display_lastline(euro) + CheckScreendump + let lines =<< trim END call setline(1, ['aaa', 'b'->repeat(200)]) set display=truncate diff --git a/test/old/testdir/test_edit.vim b/test/old/testdir/test_edit.vim @@ -2057,6 +2057,7 @@ endfunc " Test for positioning cursor after CTRL-R expression failed func Test_edit_ctrl_r_failed() + CheckScreendump CheckRunVimInTerminal let buf = RunVimInTerminal('', #{rows: 6, cols: 60}) diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim @@ -847,18 +847,6 @@ func Test_mode() execute "normal! gR\<C-o>g@l\<Esc>" call assert_equal('n-niV', g:current_modes) - " Test statusline updates for overstrike mode - if CanRunVimInTerminal() - let buf = RunVimInTerminal('', {'rows': 12}) - call term_sendkeys(buf, ":set laststatus=2 statusline=%!mode(1)\<CR>") - call term_sendkeys(buf, ":") - call TermWait(buf) - call VerifyScreenDump(buf, 'Test_mode_1', {}) - call term_sendkeys(buf, "\<Insert>") - call TermWait(buf) - call VerifyScreenDump(buf, 'Test_mode_2', {}) - call StopVimInTerminal(buf) - endif if has('terminal') term @@ -876,6 +864,22 @@ func Test_mode() delfunction OperatorFunc endfunc +" Test for the mode() function using Screendump feature +func Test_mode_screendump() + CheckScreendump + + " Test statusline updates for overstrike mode + let buf = RunVimInTerminal('', {'rows': 12}) + call term_sendkeys(buf, ":set laststatus=2 statusline=%!mode(1)\<CR>") + call term_sendkeys(buf, ":") + call TermWait(buf) + call VerifyScreenDump(buf, 'Test_mode_1', {}) + call term_sendkeys(buf, "\<Insert>") + call TermWait(buf) + call VerifyScreenDump(buf, 'Test_mode_2', {}) + call StopVimInTerminal(buf) +endfunc + " Test for append() func Test_append() enew! @@ -914,7 +918,7 @@ func Test_setline() call setline(3, v:_null_list) call setline(2, ["baz"]) call assert_equal(['bar', 'baz'], getline(1, '$')) - close! + bw! endfunc func Test_getbufvar() diff --git a/test/old/testdir/test_hlsearch.vim b/test/old/testdir/test_hlsearch.vim @@ -68,6 +68,7 @@ func Test_hlsearch_eol_highlight() endfunc func Test_hlsearch_Ctrl_R() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -86,6 +87,7 @@ func Test_hlsearch_Ctrl_R() endfunc func Test_hlsearch_clipboard() + CheckScreendump CheckRunVimInTerminal CheckFeature clipboard_working diff --git a/test/old/testdir/test_match.vim b/test/old/testdir/test_match.vim @@ -344,6 +344,7 @@ func Test_matchdelete_error() endfunc func Test_matchclear_other_window() + CheckScreendump CheckRunVimInTerminal let buf = OtherWindowCommon() call term_sendkeys(buf, ":call clearmatches(winid)\<CR>") @@ -354,6 +355,7 @@ func Test_matchclear_other_window() endfunc func Test_matchadd_other_window() + CheckScreendump CheckRunVimInTerminal let buf = OtherWindowCommon() call term_sendkeys(buf, ":call matchadd('Search', 'Hello', 1, -1, #{window: winid})\<CR>") @@ -365,6 +367,7 @@ func Test_matchadd_other_window() endfunc func Test_match_in_linebreak() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -372,15 +375,15 @@ func Test_match_in_linebreak() call printf('%s]%s', repeat('x', 50), repeat('x', 70))->setline(1) call matchaddpos('ErrorMsg', [[1, 51]]) END - call writefile(lines, 'XscriptMatchLinebreak') + call writefile(lines, 'XscriptMatchLinebreak', 'D') let buf = RunVimInTerminal('-S XscriptMatchLinebreak', #{rows: 10}) call VerifyScreenDump(buf, 'Test_match_linebreak', {}) call StopVimInTerminal(buf) - call delete('XscriptMatchLinebreak') endfunc func Test_match_with_incsearch() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -388,7 +391,7 @@ func Test_match_with_incsearch() call setline(1, range(20)) call matchaddpos('ErrorMsg', [3]) END - call writefile(lines, 'XmatchWithIncsearch') + call writefile(lines, 'XmatchWithIncsearch', 'D') let buf = RunVimInTerminal('-S XmatchWithIncsearch', #{rows: 6}) call VerifyScreenDump(buf, 'Test_match_with_incsearch_1', {}) @@ -397,7 +400,6 @@ func Test_match_with_incsearch() call term_sendkeys(buf, "\<CR>") call StopVimInTerminal(buf) - call delete('XmatchWithIncsearch') endfunc " Test for deleting matches outside of the screen redraw top/bottom lines @@ -421,6 +423,7 @@ func Test_matchdelete_redraw() endfunc func Test_match_tab_with_linebreak() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END diff --git a/test/old/testdir/test_menu.vim b/test/old/testdir/test_menu.vim @@ -3,6 +3,8 @@ source check.vim CheckFeature menu +source screendump.vim + func Test_load_menu() try source $VIMRUNTIME/menu.vim @@ -612,4 +614,50 @@ func Test_only_modifier() tunmenu a.b endfunc +func Test_unmenu_while_listing_menus() + CheckRunVimInTerminal + + let lines =<< trim END + set nocompatible + unmenu * + for i in range(1, 999) + exe 'menu ' .. 'foo.' .. i .. ' bar' + endfor + au CmdlineLeave : call timer_start(0, {-> execute('unmenu *')}) + END + call writefile(lines, 'Xmenuclear', 'D') + let buf = RunVimInTerminal('-S Xmenuclear', {'rows': 10}) + + " this was using freed memory + call term_sendkeys(buf, ":menu\<CR>") + call TermWait(buf, 50) + call term_sendkeys(buf, "G") + call TermWait(buf, 50) + call term_sendkeys(buf, "\<CR>") + + call StopVimInTerminal(buf) +endfunc + +" Test for opening a menu drawn in the cmdline area +func Test_popupmenu_cmdline() + CheckScreendump + CheckRunVimInTerminal + + let lines =<< trim END + set mousemodel=popup + menu PopUp.Test1 :<CR> + menu PopUp.Test2 :<CR> + menu PopUp.Test3 :<CR> + call setline(1, repeat(['abcde'], 5)) + END + call writefile(lines, 'Xpopupcmdline', 'D') + let buf = RunVimInTerminal('-S Xpopupcmdline', {'rows': 4}) + + " cmdline area should be cleared when popupmenu that covered it is closed + call term_sendkeys(buf, "\<RightMouse>\<RightRelease>\<Esc>") + call VerifyScreenDump(buf, 'Test_popupmenu_cmdline_1', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_messages.vim b/test/old/testdir/test_messages.vim @@ -400,6 +400,7 @@ func Test_message_more_scrollback() endfunc func Test_message_not_cleared_after_mode() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -435,6 +436,7 @@ func Test_message_not_cleared_after_mode() endfunc func Test_mode_cleared_after_silent_message() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -459,6 +461,7 @@ endfunc " Test verbose message before echo command func Test_echo_verbose_system() + CheckScreendump CheckRunVimInTerminal CheckUnix " needs the "seq" command CheckNotMac " the macos TMPDIR is too long for snapshot testing diff --git a/test/old/testdir/test_move.vim b/test/old/testdir/test_move.vim @@ -47,6 +47,7 @@ func Test_move() endfunc func Test_move_undo() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END diff --git a/test/old/testdir/test_put.vim b/test/old/testdir/test_put.vim @@ -248,6 +248,7 @@ func Test_put_visual_block_mode() endfunc func Test_put_other_window() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -267,6 +268,7 @@ func Test_put_other_window() endfunc func Test_put_in_last_displayed_line() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END diff --git a/test/old/testdir/test_search.vim b/test/old/testdir/test_search.vim @@ -886,6 +886,7 @@ func Test_incsearch_cmdline_modifier() endfunc func Test_incsearch_scrolling() + CheckScreendump CheckRunVimInTerminal call assert_equal(0, &scrolloff) call writefile([ diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim @@ -1803,6 +1803,7 @@ endfunc " Test for correct cursor position after the sign column appears or disappears. func Test_sign_cursor_position() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END diff --git a/test/old/testdir/test_startup.vim b/test/old/testdir/test_startup.vim @@ -835,6 +835,7 @@ func Test_issue_3969() endfunc func Test_start_with_tabs() + CheckScreendump CheckRunVimInTerminal let buf = RunVimInTerminal('-p a b c', {}) diff --git a/test/old/testdir/test_statusline.vim b/test/old/testdir/test_statusline.vim @@ -16,6 +16,10 @@ func TearDown() endfunc func s:get_statusline() + if has('gui_running') + redraw! + sleep 1m + endif return ScreenLines(&lines - 1, &columns)[0] endfunc diff --git a/test/old/testdir/test_substitute.vim b/test/old/testdir/test_substitute.vim @@ -728,6 +728,7 @@ func Test_sub_cmd_9() endfunc func Test_sub_highlight_zero_match() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END diff --git a/test/old/testdir/test_syntax.vim b/test/old/testdir/test_syntax.vim @@ -632,6 +632,7 @@ endfunc " Check highlighting for a small piece of C code with a screen dump. func Test_syntax_c() + CheckScreendump CheckRunVimInTerminal call writefile([ \ '/* comment line at the top */', diff --git a/test/old/testdir/test_tabpage.vim b/test/old/testdir/test_tabpage.vim @@ -688,6 +688,7 @@ func Test_tabs() endfunc func Test_tabpage_cmdheight() + CheckScreendump CheckRunVimInTerminal call writefile([ \ 'set laststatus=2', diff --git a/test/old/testdir/test_undo.vim b/test/old/testdir/test_undo.vim @@ -847,6 +847,7 @@ func Test_undo_mark() endfunc func Test_undo_after_write() + CheckScreendump " use a terminal to make undo work like when text is typed CheckRunVimInTerminal diff --git a/test/old/testdir/test_utf8.vim b/test/old/testdir/test_utf8.vim @@ -294,6 +294,7 @@ func Test_getcellwidths() endfunc func Test_setcellwidths_dump() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -311,6 +312,7 @@ endfunc " Test setcellwidths() on characters that are not targets of 'ambiwidth'. func Test_setcellwidths_with_non_ambiwidth_character_dump() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END @@ -333,6 +335,7 @@ endfunc " For some reason this test causes Test_customlist_completion() to fail on CI, " so run it as the last test. func Test_zz_ambiwidth_hl_dump() + CheckScreendump CheckRunVimInTerminal let lines =<< trim END