mirror of
https://github.com/neovim/neovim.git
synced 2026-04-18 21:40:45 +00:00
feat(:restart): reattach all UIs (#38683)
This is quite easy since [command] is now only executed once on UIEnter.
This commit is contained in:
@@ -74,9 +74,8 @@ Restart Nvim
|
|||||||
1. Stops Nvim using `:qall` (or |+cmd|, if given).
|
1. Stops Nvim using `:qall` (or |+cmd|, if given).
|
||||||
2. Starts a new Nvim server using the same |v:argv| (except
|
2. Starts a new Nvim server using the same |v:argv| (except
|
||||||
`-- [file…]` files).
|
`-- [file…]` files).
|
||||||
3. Attaches the current UI to the new Nvim server and runs
|
3. Attaches all UIs to the new Nvim server and runs `[command]`
|
||||||
`[command]` on it. Other UIs (if any) will not reattach
|
on it.
|
||||||
on restart (this may change in the future).
|
|
||||||
|
|
||||||
Example: discard changes and stop with `:qall!`, then restart: >
|
Example: discard changes and stop with `:qall!`, then restart: >
|
||||||
:restart +qall!
|
:restart +qall!
|
||||||
@@ -86,7 +85,7 @@ Restart Nvim
|
|||||||
:restart lua vim.pack.update()
|
:restart lua vim.pack.update()
|
||||||
<
|
<
|
||||||
Note: Only works if the UI and server are on the same system.
|
Note: Only works if the UI and server are on the same system.
|
||||||
Note: If the UI hasn't implemented the "restart" UI event,
|
Note: If no attached UI implements the "restart" UI event,
|
||||||
this command will lead to a dangling server process.
|
this command will lead to a dangling server process.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ UI
|
|||||||
• Highlights the cmdline as you type.
|
• Highlights the cmdline as you type.
|
||||||
• Provides the |pager| as a buffer + window.
|
• Provides the |pager| as a buffer + window.
|
||||||
• Currently experimental. To enable it: `require('vim._core.ui2').enable()`
|
• Currently experimental. To enable it: `require('vim._core.ui2').enable()`
|
||||||
• |:restart| restarts Nvim and reattaches the current UI.
|
• |:restart| restarts Nvim and reattaches all UIs.
|
||||||
• |:connect| dynamically connects the current UI to the server at the given
|
• |:connect| dynamically connects the current UI to the server at the given
|
||||||
address.
|
address.
|
||||||
• |:checkhealth| shows a summary in the header for every healthcheck.
|
• |:checkhealth| shows a summary in the header for every healthcheck.
|
||||||
|
|||||||
@@ -253,24 +253,6 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
|
|||||||
remote_ui_disconnect(channel_id, err, false);
|
remote_ui_disconnect(channel_id, err, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a "restart" UI event to the UI on the given channel.
|
|
||||||
///
|
|
||||||
/// @return false if there is no UI on the channel, otherwise true
|
|
||||||
bool remote_ui_restart(uint64_t channel_id, const char *listen_addr, Error *err)
|
|
||||||
{
|
|
||||||
RemoteUI *ui = get_ui_or_err(channel_id, err);
|
|
||||||
if (!ui) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MAXSIZE_TEMP_ARRAY(args, 1);
|
|
||||||
ADD_C(args, CSTR_AS_OBJ(listen_addr));
|
|
||||||
|
|
||||||
push_call(ui, "restart", args);
|
|
||||||
ui_flush_buf(ui, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a connect UI event to the UI on the given channel
|
// Send a connect UI event to the UI on the given channel
|
||||||
void remote_ui_connect(uint64_t channel_id, char *server_addr, Error *err)
|
void remote_ui_connect(uint64_t channel_id, char *server_addr, Error *err)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void flush(void)
|
|||||||
void connect(String server_addr)
|
void connect(String server_addr)
|
||||||
FUNC_API_SINCE(14) FUNC_API_REMOTE_ONLY FUNC_API_REMOTE_IMPL FUNC_API_CLIENT_IMPL;
|
FUNC_API_SINCE(14) FUNC_API_REMOTE_ONLY FUNC_API_REMOTE_IMPL FUNC_API_CLIENT_IMPL;
|
||||||
void restart(String listen_addr)
|
void restart(String listen_addr)
|
||||||
FUNC_API_SINCE(14) FUNC_API_REMOTE_ONLY FUNC_API_REMOTE_IMPL FUNC_API_CLIENT_IMPL;
|
FUNC_API_SINCE(14) FUNC_API_REMOTE_ONLY FUNC_API_CLIENT_IMPL;
|
||||||
void suspend(void)
|
void suspend(void)
|
||||||
FUNC_API_SINCE(3);
|
FUNC_API_SINCE(3);
|
||||||
void set_title(String title)
|
void set_title(String title)
|
||||||
|
|||||||
@@ -5081,15 +5081,9 @@ static void ex_restart(exarg_T *eap)
|
|||||||
arena_mem_free(result_mem);
|
arena_mem_free(result_mem);
|
||||||
result_mem = NULL;
|
result_mem = NULL;
|
||||||
|
|
||||||
// Send restart event with new listen address to current UI.
|
// Send restart event with new listen address to all UIs.
|
||||||
if (!no_ui && !remote_ui_restart(current_ui, listen_addr, &err)) {
|
ui_call_restart(cstr_as_string(listen_addr));
|
||||||
if (ERROR_SET(&err)) {
|
ui_flush();
|
||||||
ELOG("%s", err.msg); // UI disappeared already?
|
|
||||||
api_clear_error(&err);
|
|
||||||
}
|
|
||||||
xfree(listen_addr);
|
|
||||||
goto fail_2;
|
|
||||||
}
|
|
||||||
xfree(listen_addr);
|
xfree(listen_addr);
|
||||||
|
|
||||||
char *quit_cmd = (eap->do_ecmd_cmd) ? eap->do_ecmd_cmd : "qall";
|
char *quit_cmd = (eap->do_ecmd_cmd) ? eap->do_ecmd_cmd : "qall";
|
||||||
|
|||||||
@@ -4263,22 +4263,36 @@ describe('TUI client', function()
|
|||||||
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()
|
local _, screen_server, screen_client = start_tui_and_remote_client()
|
||||||
|
|
||||||
-- The remote client should attach to the new server.
|
-- Both clients should attach to the new server.
|
||||||
feed_data(':restart +qall!\n')
|
feed_data(':restart +qall!\n')
|
||||||
screen_client:expect([[
|
local screen_restarted = [[
|
||||||
^ |
|
^ |
|
||||||
{100:~ }|*3
|
{100:~ }|*3
|
||||||
{3:[No Name] }|
|
{3:[No Name] }|
|
||||||
|
|
|
|
||||||
{5:-- TERMINAL --} |
|
{5:-- TERMINAL --} |
|
||||||
]])
|
]]
|
||||||
screen_server:expect({ any = vim.pesc('[Process exited 0]') })
|
screen_client:expect(screen_restarted)
|
||||||
|
screen_server:expect(screen_restarted)
|
||||||
|
|
||||||
feed_data(':echo "GUI Running: " .. has("gui_running")\013')
|
feed_data(':echo "GUI Running: " .. has("gui_running")\013')
|
||||||
screen_client:expect({ any = 'GUI Running: 0' })
|
screen_client:expect({ any = 'GUI Running: 0' })
|
||||||
|
|
||||||
feed_data(':q!\r')
|
-- The :vsplit command should only be executed once.
|
||||||
|
feed_data(':restart vsplit\r')
|
||||||
|
screen_restarted = [[
|
||||||
|
^ │ |
|
||||||
|
{100:~ }│{100:~ }|*3
|
||||||
|
{3:[No Name] }{2:[No Name] }|
|
||||||
|
|
|
||||||
|
{5:-- TERMINAL --} |
|
||||||
|
]]
|
||||||
|
screen_client:expect(screen_restarted)
|
||||||
|
screen_server:expect(screen_restarted)
|
||||||
|
|
||||||
|
feed_data(':qall!\r')
|
||||||
screen_client:expect({ any = vim.pesc('[Process exited 0]') })
|
screen_client:expect({ any = vim.pesc('[Process exited 0]') })
|
||||||
|
screen_server:expect({ any = vim.pesc('[Process exited 0]') })
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function start_headless_server_and_client(use_testlog)
|
local function start_headless_server_and_client(use_testlog)
|
||||||
|
|||||||
Reference in New Issue
Block a user