diff --git a/src/client.cc b/src/client.cc index da218b7c..9c3ffc3a 100644 --- a/src/client.cc +++ b/src/client.cc @@ -86,9 +86,9 @@ void Client::handle_available_input(EventMode mode) context().print_status({ error.what().str(), get_face("Error") }); context().hooks().run_hook("RuntimeError", error.what(), context()); } - catch (Kakoune::client_removed&) + catch (Kakoune::client_removed& removed) { - ClientManager::instance().remove_client(*this); + ClientManager::instance().remove_client(*this, removed.graceful); } } diff --git a/src/client_manager.cc b/src/client_manager.cc index aab87ea2..ceceb15f 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -50,9 +50,9 @@ Client* ClientManager::create_client(std::unique_ptr&& ui, client->context().hooks().run_hook("RuntimeError", error.what(), client->context()); } - catch (Kakoune::client_removed&) + catch (Kakoune::client_removed& removed) { - m_clients.pop_back(); + remove_client(*client, removed.graceful); return nullptr; } @@ -69,13 +69,16 @@ void ClientManager::handle_pending_inputs() const client->handle_available_input(EventMode::Pending); } -void ClientManager::remove_client(Client& client) +void ClientManager::remove_client(Client& client, bool graceful) { auto it = find_if(m_clients, [&](const std::unique_ptr& ptr) { return ptr.get() == &client; }); kak_assert(it != m_clients.end()); m_clients.erase(it); + + if (not graceful and m_clients.empty()) + BufferManager::instance().backup_modified_buffers(); } WindowAndSelections ClientManager::get_free_window(Buffer& buffer) diff --git a/src/client_manager.hh b/src/client_manager.hh index 3db5fb8f..cd7f12bf 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -7,7 +7,12 @@ namespace Kakoune { -struct client_removed{}; +struct client_removed +{ + client_removed(bool graceful) : graceful{graceful} {} + + const bool graceful; +}; struct WindowAndSelections { @@ -39,7 +44,7 @@ public: Client* get_client_ifp(StringView name); Client& get_client(StringView name); bool validate_client_name(StringView name) const; - void remove_client(Client& client); + void remove_client(Client& client, bool graceful); using ClientList = Vector, MemoryDomain::Client>; using iterator = ClientList::const_iterator; diff --git a/src/commands.cc b/src/commands.cc index 034dd483..d46c8db5 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -299,7 +299,7 @@ void quit() } } // unwind back to this client event handler. - throw client_removed{}; + throw client_removed{ true }; } const CommandDesc quit_cmd = { diff --git a/src/main.cc b/src/main.cc index fbf61fbf..31bc2cfa 100644 --- a/src/main.cc +++ b/src/main.cc @@ -309,7 +309,7 @@ void create_local_client(std::unique_ptr ui, StringView init_comm signal(SIGHUP, [](int) { if (client) - ClientManager::instance().remove_client(*client); + ClientManager::instance().remove_client(*client, false); client = nullptr; }); } diff --git a/src/remote.cc b/src/remote.cc index d4a84aa7..1e1edc23 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -391,12 +391,12 @@ Key RemoteUI::get_key() } catch (peer_disconnected&) { - throw client_removed{}; + throw client_removed{ false }; } catch (socket_error&) { write_to_debug_buffer("ungraceful deconnection detected"); - throw client_removed{}; + throw client_removed{ false }; } }