diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 51332571aa..f2437588d1 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1209,9 +1209,8 @@ ZZ Write current file, if modified, and close the current ZQ Quit without checking for changes (same as ":q!"). *ZR* -[count]ZR Mapped to |:restart|. |default-mappings| - If a [count] is given, restarts without checking for - changes (same as ":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 41743b0a7f..63da98d72f 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -69,7 +69,7 @@ Restart Nvim *:restart* :restart [+cmd] [command] - Restarts Nvim. + Restarts Nvim. See also |ZR|. 1. Stops Nvim using `:qall` (or |+cmd|, if given). 2. Starts a new Nvim server using the same |v:argv| (except @@ -88,9 +88,6 @@ Restart Nvim Note: If no attached UI implements the "restart" UI event, this command will lead to a dangling server process. - Also see |ZR|. - - ------------------------------------------------------------------------------ Connect UI to a different server diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 4feaf4f1b8..9b45d01e11 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -115,8 +115,7 @@ BUILD DEFAULTS -• Mappings: - • |ZR| in Normal mode to |:restart| +• todo DIAGNOSTICS @@ -126,6 +125,7 @@ EDITOR • |gf| and || support `file://…` URIs. • |:log| opens log files. +• |ZR| restarts Nvim (|:restart|). EVENTS diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index e05d1893d1..d738638575 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -171,7 +171,6 @@ you never want any default mappings, call |:mapclear| early in your config. - Treesitter defaults |treesitter-defaults| - |v_an| |v_in| - |v_]n| |v_[n| -- |ZR| DEFAULT AUTOCOMMANDS *default-autocmds* @@ -389,6 +388,7 @@ Input/Mappings: Normal commands: - |gO| shows a filetype-defined "outline" of the current buffer. - |Q| replays the last recorded macro instead of switching to Ex mode (|gQ|). +- |ZR| performs |:restart| Options: diff --git a/runtime/lua/vim/_core/defaults.lua b/runtime/lua/vim/_core/defaults.lua index efe390d8ee..27165bbb04 100644 --- a/runtime/lua/vim/_core/defaults.lua +++ b/runtime/lua/vim/_core/defaults.lua @@ -482,14 +482,6 @@ do end end, { desc = 'Select child (inner) node' }) end - - -- Z layer mappings - do - vim.keymap.set('n', 'ZR', function() - local args = vim.v.count >= 1 and { '+qall!' } or nil - cmd({ cmd = 'restart', args = args }) - end, { desc = ':help ZR' }) - end end --- Default menus diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 9860937612..7a5a238df2 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3299,6 +3299,15 @@ static void nv_Zet(cmdarg_T *cap) do_cmdline_cmd("q!"); break; + // "ZR": restart. With count, restart without checking for changes. + case 'R': + if (cap->count0 >= 1) { + do_cmdline_cmd("restart +qall!"); + } else { + do_cmdline_cmd("restart"); + } + break; + default: clearopbeep(cap->oap); } diff --git a/test/client/uv_stream.lua b/test/client/uv_stream.lua index 220938307a..464f52a609 100644 --- a/test/client/uv_stream.lua +++ b/test/client/uv_stream.lua @@ -122,7 +122,9 @@ function SocketStream:read_stop() end function SocketStream:close() - uv.close(self._socket) + if not self._socket:is_closing() then + uv.close(self._socket) + end end --- Stream over child process stdio. diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 5d6b264578..5ada3ebd0a 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -10,7 +10,6 @@ local Screen = require('test.functional.ui.screen') local tt = require('test.functional.testterm') local eq = t.eq -local pcall_err = t.pcall_err local feed_data = tt.feed_data local clear = n.clear local command = n.command @@ -208,10 +207,74 @@ describe('TUI :restart', function() before_each(n.clear) after_each(n.check_close) + ---@param exp boolean Restart expected + ---@param sess table Session + ---@param addr string + local function assert_restarted(exp, sess, addr) + local s = sess + retry(nil, 5000, function() + if exp then + s:close() + s = n.connect(addr) + end + + -- Cheesy but reliable: :restart drops "-- [files…]", so empty v:argf means restart happened. + -- TODO(justinmk): add `v:startreason`, `v:starttime` + local _, argf = s:request('nvim_eval', 'v:argf') + ok(vim.tbl_count(argf) == (exp and 0 or 1), exp and 'empty v:argf' or 'nonempty v:argf', argf) + end) + end + it('validation', function() eq('Vim(restart):E481: No range allowed: :1restart', t.pcall_err(n.command, ':1restart')) end) + it('ZR', function() + -- Just exercise ZR, don't need to test all :restart functionality here. + t.skip(is_os('win'), 'FIXME: --listen not preserved by :restart on Windows #38539') + local server_pipe = new_pipename() + local server_session + finally(function() + if server_session and not server_session.closed then + server_session:close() + end + end) + local screen = tt.setup_child_nvim({ + '-u', + 'NONE', + '-i', + 'NONE', + '--listen', + server_pipe, + '--cmd', + 'set notermguicolors', + '--', + 'file1.txt', -- XXX: see comment in assert_restarted() + }, { + 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) + screen:expect({ any = 'file1%.txt' }) + + server_session = n.connect(server_pipe) + assert_restarted(false, server_session, server_pipe) + + -- ZR on modified buffer fails with E37. + tt.feed_data('ifoo\027') + tt.feed_data('ZR') + screen:expect({ any = 'E37' }) + + -- [count]ZR discards unsaved changes. + tt.feed_data('1ZR') + + assert_restarted(true, server_session, server_pipe) + end) + it('works', function() local server_pipe = new_pipename() local screen = tt.setup_child_nvim({