From 845b66dd4a50d7b54050990e27919549c331e1bb Mon Sep 17 00:00:00 2001 From: Nathan Zeng Date: Mon, 29 Jun 2026 07:55:23 -0700 Subject: [PATCH] feat(:restart)!: ":restart" (no bang) saves/restores session #40321 Problem: `:restart` does not preserve window layout, etc. Solution: - Change `:restart` to save/restore a session automatically. - Introduce "bang" variant `:restart!` to restart *without* session save/restore. - Introduce `v:startreason`. - `ZR` maps to `:restart!`. --- runtime/doc/editing.txt | 4 +- runtime/doc/gui.txt | 9 +- runtime/doc/news.txt | 3 +- runtime/doc/vvars.txt | 3 +- runtime/lua/vim/_core/server.lua | 61 +++++++++++ runtime/lua/vim/_meta/vvars.gen.lua | 3 +- src/nvim/eval/vars.c | 2 +- src/nvim/ex_cmds.lua | 2 +- src/nvim/ex_docmd.c | 35 +++++- src/nvim/normal.c | 4 +- src/nvim/vvars.lua | 3 +- test/functional/core/main_spec.lua | 2 +- test/functional/core/server_spec.lua | 12 +- test/functional/terminal/tui_spec.lua | 151 +++++++++++++++++++------- 14 files changed, 231 insertions(+), 63 deletions(-) diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 824fe4d87e..2f3e45cf50 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1229,8 +1229,8 @@ ZZ Write current file, if modified, and close the current ZQ Quit without checking for changes (same as ":q!"). *ZR* -[count]ZR Performs |:restart|. If a [count] is given, restarts - without checking for changes (":restart +qall!"). +[count]ZR Performs |:restart!|. If a [count] is given, restarts + without checking for changes (":restart! +qall!"). MULTIPLE WINDOWS AND BUFFERS *window-exit* diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index c24c21d133..35ae45432b 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -75,9 +75,10 @@ Stop or detach the current UI ------------------------------------------------------------------------------ Restart Nvim - *:restart* -:restart [+cmd] [command] + *:restart* *:restart!* +:restart[!] [+cmd] [command] Restarts Nvim. Sets |v:exitreason|. See also |ZR|. + When [!] is included, the session is not restored. 1. Stops Nvim using `:qall` (or |+cmd|, if given). 2. Starts a new Nvim server using the same |v:argv| (except @@ -89,9 +90,9 @@ Restart Nvim Example: discard changes and stop with `:qall!`, then restart: > :restart +qall! < Example: restart and restore the current session: > - :mksession! Session.vim | restart source Session.vim + :mksession! Session.vim | restart! source Session.vim < Example: restart and update plugins: > - :restart lua vim.pack.update() + :restart packupdate < Note: • Only works if the UI and server are on the same system. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index aa850b8f3d..6b5bf77930 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -195,7 +195,8 @@ EDITOR • The |cmdwin-char| is shown via 'statuscolumn'. • |gf| and || support `file://…` URIs. • |:log| opens log files. -• |ZR| restarts Nvim (|:restart|). +• |:restart| now restores the current session while |:restart!| does not. +• |ZR| restarts Nvim (|:restart!|). • |:uptime| displays uptime. • |:packupdate| and |:packdel| for managing |vim.pack|. • 'scrollback' is now also valid in |prompt-buffer| buffers to limit the diff --git a/runtime/doc/vvars.txt b/runtime/doc/vvars.txt index 084124cb92..dc29d0059c 100644 --- a/runtime/doc/vvars.txt +++ b/runtime/doc/vvars.txt @@ -637,7 +637,8 @@ v:stacktrace v:startreason The reason Nvim started. Possible values: - "normal" normal startup. - - "restart" started by |:restart| or |ZR|. + - "restart" started by |:restart|. + - "restart!" started by |:restart!| or |ZR|. Read-only. diff --git a/runtime/lua/vim/_core/server.lua b/runtime/lua/vim/_core/server.lua index 514a73f620..2127ec3c3d 100644 --- a/runtime/lua/vim/_core/server.lua +++ b/runtime/lua/vim/_core/server.lua @@ -1,3 +1,5 @@ +local fs = vim.fs +local uv = vim.uv -- For "--listen" and related functionality. local M = {} @@ -154,4 +156,63 @@ function M.rebind_after_restart(canonical_addr, expected_uis) end) end +-- Called by ex_restart(). Saves the current session and calls back to +-- ex_restart() with the necessary arguments to restore the session. +-- TODO: https://github.com/neovim/neovim/issues/34204 +--- @param eap vim._core.ExCmdArgs +--- @param extra { quit_cmd: string } +function M.ex_session_restart(eap, extra) + -- Commands to run after restart + local after_cmd = eap.args + assert(not after_cmd:find(']==]')) + + -- Use custom quit command if provided + local quit_cmd = 'qall' + if extra.quit_cmd ~= '' then + quit_cmd = extra.quit_cmd + end + + -- Preserve the value of v:this_session + local this_session = vim.v.this_session + assert(not this_session:find(']==]')) + + -- Get temp file to write session to + local temp_dir = fs.abspath(fs.dirname(fs.dirname(vim.fn.tempname()))) + assert(not temp_dir:find(']==]')) + local fd, session = uv.fs_mkstemp(fs.joinpath(temp_dir, 'restart_session_XXXXXX')) + if not fd then + error('Failed to get temporary filename for restart session') + end + uv.fs_close(fd) + + -- Write session + local session_arg = vim.fn.fnameescape(session) + vim.cmd('%argdelete') + vim.cmd.mksession { session_arg, bang = true } + + -- Lua commands to restore the session and remove the session file + local after_list = {} + table.insert(after_list, ('vim.cmd("source %s")'):format(session_arg)) + table.insert(after_list, ('pcall(vim.fs.rm, [==[%s]==])'):format(session)) + table.insert(after_list, ('vim.v.this_session = [==[%s]==]'):format(this_session)) + -- User provided command + if after_cmd ~= '' then + table.insert(after_list, ('vim.cmd([==[%s]==])'):format(after_cmd)) + end + -- Concatenate everything together + local after = 'lua ' .. table.concat(after_list, ';') + + -- Restart Neovim and run our Lua commands + local success, msg = pcall(function() + -- "+:::" special argument tells the C handler that this is actually a non-bang restart + -- That way, v:startreason can be set correctly + vim.cmd.restart { '+:::', quit_cmd, after, bang = true } + end) + + if not success then + fs.rm(session, { force = true }) + error(msg) + end +end + return M diff --git a/runtime/lua/vim/_meta/vvars.gen.lua b/runtime/lua/vim/_meta/vvars.gen.lua index da6710da7d..141fc70426 100644 --- a/runtime/lua/vim/_meta/vvars.gen.lua +++ b/runtime/lua/vim/_meta/vvars.gen.lua @@ -669,7 +669,8 @@ vim.v.stacktrace = ... --- The reason Nvim started. Possible values: --- - "normal" normal startup. ---- - "restart" started by `:restart` or `ZR`. +--- - "restart" started by `:restart`. +--- - "restart!" started by `:restart!` or `ZR`. --- --- Read-only. --- @type string diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index a74861a5df..d8da53dd86 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -349,7 +349,7 @@ void evalvars_init(void) // Set v:startreason via environment variable const char *startreason = os_getenv_noalloc(ENV_STARTREASON); - if (strequal(startreason, "normal") || strequal(startreason, "restart")) { + if (strequal(startreason, "restart!") || strequal(startreason, "restart")) { set_vim_var_string(VV_STARTREASON, startreason, -1); } if (os_env_exists(ENV_STARTREASON, false)) { diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index f6b63133fe..0ea7642d08 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -2291,7 +2291,7 @@ M.cmds = { }, { command = 'restart', - flags = bit.bor(CMDARG, EXTRA, NOTRLCOM), + flags = bit.bor(BANG, CMDARG, EXTRA, NOTRLCOM), addr_type = 'ADDR_NONE', func = 'ex_restart', }, diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e8dd3e9727..74a87652ff 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4969,6 +4969,34 @@ static void ex_quitall(exarg_T *eap) /// ":restart +cmd ": restart the Nvim server using ":cmd" and runs in the new server. static void ex_restart(exarg_T *eap) { + if (!eap->forceit) { + // Pass +cmd via the `extra` slot of nlua_call_excmd + dict_T *extra_d = tv_dict_alloc(); + tv_dict_add_str(extra_d, S_LEN("quit_cmd"), eap->do_ecmd_cmd ? eap->do_ecmd_cmd : ""); + typval_T extra_tv = { .v_type = VAR_DICT, .vval.v_dict = extra_d }; + nlua_call_excmd("vim._core.server", "ex_session_restart", eap, &cmdmod, &extra_tv); + tv_clear(&extra_tv); + return; + } + + const char *startreason = "restart!"; + char *quit_cmd = (eap->do_ecmd_cmd) ? eap->do_ecmd_cmd : "qall"; + char *after_cmd = eap->arg; + + // "+:::" is how ex_session_restart() signals that it (recursively) called into :restart. + if (strequal(quit_cmd, ":::")) { + startreason = "restart"; + // Set quit_cmd and after_cmd from args + if (eap->argc > 1) { + eap->args[1][eap->arglens[1]] = NUL; + quit_cmd = eap->args[1]; + after_cmd = eap->argc > 2 ? eap->args[2] : ""; + } else { + emsg("restart failed: +cmd did not quit the server"); + return; + } + } + Error err = ERROR_INIT; const bool no_ui = !ui_active(); const char *exepath = get_vim_var_str(VV_PROGPATH); @@ -5046,7 +5074,7 @@ static void ex_restart(exarg_T *eap) #endif dict_T *env = create_environment(NULL, false, false, false, NULL); - tv_dict_add_str(env, S_LEN(ENV_STARTREASON), "restart"); + tv_dict_add_str(env, S_LEN(ENV_STARTREASON), startreason); #ifdef MSWIN tv_dict_add_str(env, S_LEN(ENV_RESTART_ALLOC_CONSOLE), "1"); #endif @@ -5082,12 +5110,12 @@ static void ex_restart(exarg_T *eap) arena_mem_free(result_mem); result_mem = NULL; - if (*eap->arg != NUL) { + if (*after_cmd != NUL) { // Execute [command] on new server on UIEnter. MAXSIZE_TEMP_DICT(autocmd_opts, 3); PUT_C(autocmd_opts, "once", BOOLEAN_OBJ(true)); PUT_C(autocmd_opts, "nested", BOOLEAN_OBJ(true)); - PUT_C(autocmd_opts, "command", CSTR_AS_OBJ(eap->arg)); + PUT_C(autocmd_opts, "command", CSTR_AS_OBJ(after_cmd)); MAXSIZE_TEMP_ARRAY(autocmd_args, 2); ADD_C(autocmd_args, CSTR_AS_OBJ("UIEnter")); ADD_C(autocmd_args, DICT_OBJ(autocmd_opts)); @@ -5142,7 +5170,6 @@ static void ex_restart(exarg_T *eap) set_vim_var_string(VV_EXITREASON, S_LEN("restart")); - char *quit_cmd = (eap->do_ecmd_cmd) ? eap->do_ecmd_cmd : "qall"; char *quit_cmd_copy = NULL; // Prepend "confirm " to cmd if :confirm is used diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f5feaf195a..1e21114970 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3287,9 +3287,9 @@ static void nv_Zet(cmdarg_T *cap) // "ZR": restart. With count, restart without checking for changes. case 'R': if (cap->count0 >= 1) { - do_cmdline_cmd("restart +qall!"); + do_cmdline_cmd("restart! +qall!"); } else { - do_cmdline_cmd("restart"); + do_cmdline_cmd("restart!"); } break; diff --git a/src/nvim/vvars.lua b/src/nvim/vvars.lua index e28c77ec24..58408c485e 100644 --- a/src/nvim/vvars.lua +++ b/src/nvim/vvars.lua @@ -781,7 +781,8 @@ M.vars = { desc = [=[ The reason Nvim started. Possible values: - "normal" normal startup. - - "restart" started by |:restart| or |ZR|. + - "restart" started by |:restart|. + - "restart!" started by |:restart!| or |ZR|. Read-only. ]=], diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua index c8e4791869..7db780c425 100644 --- a/test/functional/core/main_spec.lua +++ b/test/functional/core/main_spec.lua @@ -215,7 +215,7 @@ describe('vim._core', function() -- All `vim._core.*` modules are builtin. t.eq( - { 'rebind_after_restart', 'serverlist' }, + { 'ex_session_restart', 'rebind_after_restart', 'serverlist' }, n.exec_lua([[local k = vim.tbl_keys(require('vim._core.server')); table.sort(k); return k]]) ) local expected = { diff --git a/test/functional/core/server_spec.lua b/test/functional/core/server_spec.lua index f830762199..d1ab9e3cea 100644 --- a/test/functional/core/server_spec.lua +++ b/test/functional/core/server_spec.lua @@ -402,8 +402,8 @@ describe('startup --listen', function() end) end) -it(':restart works in headless server (no UI)', function() - t.skip(is_os('win'), 'FIXME: --listen not preserved by :restart on Windows') +it(':restart! works in headless server (no UI)', function() + t.skip(is_os('win'), 'FIXME: --listen not preserved by :restart! on Windows') local nvim0 = clear() local server_pipe = n.new_pipename() @@ -428,14 +428,14 @@ it(':restart works in headless server (no UI)', function() end) n.set_session(n.connect(server_pipe)) - n.expect_exit(n.command, 'restart') + n.expect_exit(n.command, 'restart!') n.set_session(n.connect(server_pipe)) eq(1, api.nvim_get_vvar('vim_did_enter')) - eq('restart', api.nvim_get_vvar('startreason')) - eq('restart', n.eval('g:early_startreason')) + eq('restart!', api.nvim_get_vvar('startreason')) + eq('restart!', n.eval('g:early_startreason')) -- TODO: [command] is currently not executed without UI - -- n.expect_exit(n.command, 'restart lua _G.new_server = 1') + -- n.expect_exit(n.command, 'restart! lua _G.new_server = 1') -- n.set_session(n.connect(server_pipe)) -- eq(1, n.exec_lua('return _G.new_server')) end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 441bb21e4a..fc54c1ca64 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -269,11 +269,86 @@ describe('TUI :restart', function() end it('validation', function() - eq('Vim(restart):E481: No range allowed: :1restart', t.pcall_err(n.command, ':1restart')) + eq('Vim(restart):E481: No range allowed: :1restart!', t.pcall_err(n.command, ':1restart!')) + end) + + it(':restart (no bang) restores session, window layout', function() + local file = 'Xtest-restart-file' + write_file(file, 'foobar') + finally(function() + os.remove(file) + end) + + local server_pipe = new_pipename() + local server_session + finally(function() + if server_session then + server_session:close() + end + end) + local screen = tt.setup_child_nvim({ + '--clean', + '--listen', + server_pipe, + '--cmd', + 'set notermguicolors laststatus=0 noruler noshowcmd', + }, { + env = vim.tbl_extend('force', env_notermguicolors, { + -- Ignore logs, because assert_restarted may log "connection refused" while it retries. + NVIM_LOG_FILE = testlog, + }), + }) + finally(function() + os.remove(testlog) + end) + + feed_data(':edit ' .. file .. '\r') + feed_data(':wincmd v\r') + screen:expect([[ + ^foobar │foobar | + ~ │~ | + ~ │~ | + ~ │~ | + ~ │~ | + :wincmd v | + {5:-- TERMINAL --} | + ]]) + server_session = n.connect(server_pipe) + local _, starttime = server_session:request('nvim_eval', 'v:starttime') + eq({ true, '' }, { server_session:request('nvim_get_vvar', 'this_session') }) + + -- :restart + feed_data(':restart\r') + screen:expect([[ + ^foobar │foobar | + ~ │~ | + ~ │~ | + ~ │~ | + ~ │~ | + | + {5:-- TERMINAL --} | + ]]) + starttime, server_session = assert_restarted(starttime, server_session, server_pipe) + eq({ true, 'restart' }, { server_session:request('nvim_get_vvar', 'startreason') }) + eq({ true, '' }, { server_session:request('nvim_get_vvar', 'this_session') }) + + -- :restart! + feed_data(':restart!\r') + screen:expect([[ + ^ | + ~ |*4 + | + {5:-- TERMINAL --} | + ]]) + starttime, server_session = assert_restarted(starttime, server_session, server_pipe) + eq({ true, 'restart!' }, { server_session:request('nvim_get_vvar', 'startreason') }) + + feed_data(':qall!\r') + screen:expect({ any = vim.pesc('[Process exited 0]') }) end) it('ZR', function() - -- Just exercise ZR, don't need to test all :restart functionality here. + -- Just exercise ZR, don't need to test all :restart! functionality here. local server_pipe = new_pipename() local server_session finally(function() @@ -353,8 +428,8 @@ describe('TUI :restart', function() }, { env = { COLORTERM = 'truecolor' } }) screen:set_option('rgb', true) - -- 'termguicolors' support should be detected properly after :restart. - -- The value of has("gui_running") should be 0 before and after :restart. + -- 'termguicolors' support should be detected properly after :restart! + -- The value of has("gui_running") should be 0 before and after :restart! local function assert_termguicolors_and_no_gui_running() tt.feed_data(':echo "&termguicolors: " .. &termguicolors\013') screen:expect({ any = '&termguicolors: 1' }) @@ -400,14 +475,14 @@ describe('TUI :restart', function() tt.feed_data(':set nomodified\013') -- Command is run on new server. - tt.feed_data(":restart put ='Hello1'\013") + tt.feed_data(":restart! put ='Hello1'\013") screen:expect(s1) assert_new_pid() assert_exitreason() assert_termguicolors_and_no_gui_running() -- Complex command following +cmd. - tt.feed_data(":restart +qall! put ='Hello2' | put ='World2'\013") + tt.feed_data(":restart! +qall! put ='Hello2' | put ='World2'\013") screen:expect([[ | Hello2 | @@ -421,24 +496,24 @@ describe('TUI :restart', function() assert_exitreason() assert_termguicolors_and_no_gui_running() - -- Check ":restart" on an unmodified buffer. + -- Check ":restart!" on an unmodified buffer. tt.feed_data(':set nomodified\013') - tt.feed_data(':restart\013') + tt.feed_data(':restart!\013') screen:expect(s0) assert_new_pid() assert_exitreason() assert_termguicolors_and_no_gui_running() - -- Check ":restart +qall!" on an unmodified buffer. - tt.feed_data(':restart +qall!\013') + -- Check ":restart! +qall!" on an unmodified buffer. + tt.feed_data(':restart! +qall!\013') screen:expect(s0) assert_new_pid() assert_exitreason() assert_termguicolors_and_no_gui_running() - -- Check ":restart +echo" cannot restart server. + -- Check ":restart! +echo" cannot restart server. -- Check the full screen state to ensure this doesn't pollute the current UI. - tt.feed_data(':restart +echo\013') + tt.feed_data(':restart! +echo\013') screen:expect([[ ^ | {1:~}{18: }|*3 @@ -450,8 +525,8 @@ describe('TUI :restart', function() tt.feed_data('ithis will be removed\027') screen:expect({ any = vim.pesc('this will be remove^d') }) - -- Check ":confirm restart" on a modified buffer. - tt.feed_data(':confirm restart\013') + -- Check ":confirm restart!" on a modified buffer. + tt.feed_data(':confirm restart!\013') screen:expect({ any = vim.pesc('Save changes to "Untitled"?') }) -- Cancel the operation (abandons restart). @@ -460,9 +535,9 @@ describe('TUI :restart', function() -- Failed/cancelled restarts still fire QuitPre/ExitPre (but not VimLeave[Pre]). assert_exitreason('QuitPre:restart\nExitPre:restart\n') - -- Check :restart respects 'confirm' option. + -- Check :restart! respects 'confirm' option. tt.feed_data(':set confirm\013') - tt.feed_data(':restart\013') + tt.feed_data(':restart!\013') screen:expect({ any = vim.pesc('Save changes to "Untitled"?') }) tt.feed_data('C\013') screen:expect({ any = vim.pesc('[No Name]') }) @@ -470,8 +545,8 @@ describe('TUI :restart', function() -- Failed/cancelled restarts still fire QuitPre/ExitPre (but not VimLeave[Pre]). assert_exitreason('QuitPre:restart\nExitPre:restart\n') - -- Check ":confirm restart " on a modified buffer. - tt.feed_data(":confirm restart put ='Hello3'\013") + -- Check ":confirm restart! " on a modified buffer. + tt.feed_data(":confirm restart! put ='Hello3'\013") screen:expect({ any = vim.pesc('Save changes to "Untitled"?') }) tt.feed_data('N\013') screen:expect({ any = '%^Hello3' }) @@ -479,19 +554,19 @@ describe('TUI :restart', function() assert_exitreason() assert_termguicolors_and_no_gui_running() - -- Check ":confirm restart +echo" correctly ignores ":confirm" - tt.feed_data(':confirm restart +echo\013') + -- Check ":confirm restart! +echo" correctly ignores ":confirm" + tt.feed_data(':confirm restart! +echo\013') screen:expect({ any = vim.pesc('+cmd did not quit the server') }) - -- Check ":restart" on a modified buffer. + -- Check ":restart!" on a modified buffer. tt.feed_data('ithis will be removed\027') - tt.feed_data(':restart\013') + tt.feed_data(':restart!\013') screen:expect({ any = vim.pesc('Vim(qall):E37: No write since last change') }) assert_exitreason('QuitPre:restart\nExitPre:restart\n') - -- Check ":restart +qall!" on a modified buffer. + -- Check ":restart! +qall!" on a modified buffer. tt.feed_data('ithis will be removed\027') - tt.feed_data(':restart +qall!\013') + tt.feed_data(':restart! +qall!\013') screen:expect(s0) assert_new_pid() assert_exitreason() @@ -499,7 +574,7 @@ describe('TUI :restart', function() if not is_os('win') then -- No --listen conflict when server exit is delayed. - feed_data(':lua vim.schedule(function() vim.wait(100) end); vim.cmd.restart()\n') + feed_data(':lua vim.schedule(function() vim.wait(100) end); vim.cmd("restart!")\n') screen:expect(s0) assert_new_pid() assert_exitreason() @@ -515,8 +590,8 @@ describe('TUI :restart', function() {5:-- TERMINAL --} | ]]) - --- Check that ":restart" uses the updated size after terminal resize. - tt.feed_data(':restart echo "restarted"\013') + --- Check that ":restart!" uses the updated size after terminal resize. + tt.feed_data(':restart! echo "restarted"\013') screen:expect([[ ^ | {1:~}{18: }|*2 @@ -571,7 +646,7 @@ describe('TUI :restart', function() eq({ true, true }, { server_session:request('nvim_eval', expr) }) eq({ true, true }, { server_session:request('nvim_eval', has_s) }) - tt.feed_data(":restart put='foo'\013") + tt.feed_data(":restart! put='foo'\013") screen:expect([[ | ^foo | @@ -611,7 +686,7 @@ describe('TUI :restart', function() ]]) -- 'laststatus' should be 0 in the new Nvim and FileType event should be triggered. - feed_data(':restart set nowrap | edit test/functional/fixtures/bigfile.txt\r') + feed_data(':restart! set nowrap | edit test/functional/fixtures/bigfile.txt\r') screen:expect([[ ^0000;;Cc;0;BN;;;;;N;NULL;;;; | 0001;;Cc;0;BN;;;;;N;START OF HEADING;;;; | @@ -674,7 +749,7 @@ describe('TUI :restart', function() {5:-- TERMINAL --} | ]]) - feed_data(':restart echo "restarted"\r') + feed_data(':restart! echo "restarted"\r') screen:expect([[ ^ │0000;;Cc;0;BN;;;;;N| ~ │0001;;Cc;0;BN;;;;;N| @@ -685,7 +760,7 @@ describe('TUI :restart', function() {5:-- TERMINAL --} | ]]) - feed_data(':set sessionoptions-=winsize | restart\r') + feed_data(':set sessionoptions-=winsize | restart!\r') screen:expect([[ ^ │0000;;Cc;0;BN;;| ~ │0001;;Cc;0;BN;;| @@ -3069,8 +3144,8 @@ describe('TUI', function() { 'tty', 'tty' }, child_exec_lua('return { vim.uv.guess_handle(0), vim.uv.guess_handle(1) }') ) - -- Also works after :restart #38745 - feed_data(':restart lua ={ vim.uv.guess_handle(0), vim.uv.guess_handle(1) }\r') + -- Also works after :restart! #38745 + feed_data(':restart! lua ={ vim.uv.guess_handle(0), vim.uv.guess_handle(1) }\r') screen:expect([[ ^ | {100:~ }|*3 @@ -4610,11 +4685,11 @@ describe('TUI client', function() screen_server:expect(s1) end) - it(':restart works when connecting to remote instance (with its own TUI)', function() + it(':restart! works when connecting to remote instance (with its own TUI)', function() local _, screen_server, screen_client = start_tui_and_remote_client() -- Both clients should attach to the new server. - feed_data(':restart +qall!\n') + feed_data(':restart! +qall!\n') local screen_restarted = [[ ^ | {100:~ }|*3 @@ -4629,7 +4704,7 @@ describe('TUI client', function() screen_client:expect({ any = 'GUI Running: 0' }) -- The :vsplit command should only be executed once. - feed_data(':restart vsplit\r') + feed_data(':restart! vsplit\r') screen_restarted = [[ ^ │ | {100:~ }│{100:~ }|*3 @@ -4721,11 +4796,11 @@ describe('TUI client', function() screen_client:expect({ any = 'GUI Running: 0' }) end) - it(':restart works when connecting to remote instance (--headless)', function() + it(':restart! works when connecting to remote instance (--headless)', function() local _, server_pipe, screen_client = start_headless_server_and_client(false) -- The client should attach to the new server and the original server should exit. - feed_data(':restart +qall!\n') + feed_data(':restart! +qall!\n') screen_client:expect([[ ^ | {100:~ }|*4