diff --git a/src/client_manager.cc b/src/client_manager.cc index 927c1c0e..aab87ea2 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -13,7 +13,12 @@ namespace Kakoune { ClientManager::ClientManager() = default; -ClientManager::~ClientManager() = default; +ClientManager::~ClientManager() +{ + // So that clients destructor find the client manager empty + // so that local UI does not fork. + ClientList clients = std::move(m_clients); +} String ClientManager::generate_name() const { diff --git a/src/commands.cc b/src/commands.cc index d1cb9b46..3f8c06b3 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -263,6 +263,17 @@ const CommandDesc writeall_cmd = { [](const ParametersParser&, Context&){ write_all_buffers(); } }; +const CommandDesc kill_cmd = { + "kill", + nullptr, + "kill current session, quit all clients and server", + no_params, + CommandFlags::None, + CommandHelper{}, + CommandCompleter{}, + [](const ParametersParser&, Context&){ throw kill_session{}; } +}; + template void quit() { @@ -1649,6 +1660,7 @@ void register_commands() register_command(writeall_cmd); register_command(writeall_quit_cmd); register_command(quit_cmd); + register_command(kill_cmd); register_command(force_quit_cmd); register_command(write_quit_cmd); register_command(force_write_quit_cmd); diff --git a/src/commands.hh b/src/commands.hh index 9183f85f..8fdc6057 100644 --- a/src/commands.hh +++ b/src/commands.hh @@ -12,6 +12,8 @@ class Key; void register_commands(); void exec_keys(ConstArrayView keys, Context& context); +struct kill_session {}; + } #endif // commands_hh_INCLUDED diff --git a/src/main.cc b/src/main.cc index fce01de9..9d58d84c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -450,14 +450,18 @@ int run_server(StringView session, StringView init_command, if (not daemon) create_local_client(create_local_ui(dummy_ui), init_command, startup_error); - while (not terminate and (not client_manager.empty() or daemon)) + try { - client_manager.redraw_clients(); - event_manager.handle_next_events(EventMode::Normal); - client_manager.handle_pending_inputs(); - buffer_manager.clear_buffer_trash(); - string_registry.purge_unused(); + while (not terminate and (not client_manager.empty() or daemon)) + { + client_manager.redraw_clients(); + event_manager.handle_next_events(EventMode::Normal); + client_manager.handle_pending_inputs(); + buffer_manager.clear_buffer_trash(); + string_registry.purge_unused(); + } } + catch (const kill_session&) {} { Context empty_context{Context::EmptyContextFlag{}};