diff --git a/src/client_manager.cc b/src/client_manager.cc index b268df10..72063db5 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -11,26 +11,15 @@ namespace Kakoune { -struct ClientManager::Client +Client::Client(std::unique_ptr&& ui, + Window& window, String name) + : m_user_interface(std::move(ui)), + m_input_handler(*m_user_interface), + m_name(std::move(name)) { - Client(std::unique_ptr&& ui, Window& window, - String name) - : user_interface(std::move(ui)), - input_handler(*user_interface), - name(std::move(name)) - { - kak_assert(not this->name.empty()); - context().change_editor(window); - } - Client(Client&&) = delete; - Client& operator=(Client&& other) = delete; - - Context& context() { return input_handler.context(); } - - std::unique_ptr user_interface; - InputHandler input_handler; - String name; -}; + kak_assert(not m_name.empty()); + context().change_editor(window); +} ClientManager::ClientManager() = default; ClientManager::~ClientManager() = default; @@ -43,7 +32,7 @@ String ClientManager::generate_name() const bool found = false; for (auto& client : m_clients) { - if (client->name == name) + if (client->m_name == name) { found = true; break; @@ -54,53 +43,57 @@ String ClientManager::generate_name() const } } -void ClientManager::create_client(std::unique_ptr&& ui, - const String& init_commands) +Client* ClientManager::create_client(std::unique_ptr&& ui, + const String& init_commands) { Buffer& buffer = **BufferManager::instance().begin(); - m_clients.emplace_back(new Client{std::move(ui), get_unused_window_for_buffer(buffer), - generate_name()}); - Context* context = &m_clients.back()->context(); + Client* client = new Client{std::move(ui), get_unused_window_for_buffer(buffer), + generate_name()}; + m_clients.emplace_back(client); try { - CommandManager::instance().execute(init_commands, *context); + CommandManager::instance().execute(init_commands, client->context()); } catch (Kakoune::runtime_error& error) { - context->print_status({ error.what(), get_color("Error") }); - context->hooks().run_hook("RuntimeError", error.what(), *context); + client->context().print_status({ error.what(), get_color("Error") }); + client->context().hooks().run_hook("RuntimeError", error.what(), + client->context()); } catch (Kakoune::client_removed&) { m_clients.pop_back(); - return; + return nullptr; } - context->ui().set_input_callback([context, this]() { + client->m_user_interface->set_input_callback([client, this]() { try { - context->input_handler().handle_available_inputs(); - context->window().forget_timestamp(); + client->m_input_handler.handle_available_inputs(); + client->context().window().forget_timestamp(); } catch (Kakoune::runtime_error& error) { - context->print_status({ error.what(), get_color("Error") }); - context->hooks().run_hook("RuntimeError", error.what(), *context); + client->context().print_status({ error.what(), get_color("Error") }); + client->context().hooks().run_hook("RuntimeError", error.what(), + client->context()); } catch (Kakoune::client_removed&) { - ClientManager::instance().remove_client_by_context(*context); + ClientManager::instance().remove_client(*client); } ClientManager::instance().redraw_clients(); }); redraw_clients(); + + return client; } -void ClientManager::remove_client_by_context(Context& context) +void ClientManager::remove_client(Client& client) { for (auto it = m_clients.begin(); it != m_clients.end(); ++it) { - if (&(*it)->context() == &context) + if (it->get() == &client) { m_clients.erase(it); return; @@ -139,7 +132,7 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer) continue; if (client->context().editor().is_editing()) - throw runtime_error("client '" + client->name + "' is inserting in '" + + throw runtime_error("client '" + client->m_name + "' is inserting in '" + buffer.display_name() + '\''); // change client context to edit the first buffer which is not the @@ -161,40 +154,32 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer) m_windows.erase(end, m_windows.end()); } -void ClientManager::set_client_name(Context& context, String name) +void ClientManager::set_client_name(Client& client, String name) { auto it = find_if(m_clients, [&name](std::unique_ptr& client) - { return client->name == name; }); - if (it != m_clients.end() and &(*it)->context() != &context) + { return client->m_name == name; }); + if (it != m_clients.end() and it->get() != &client) throw runtime_error("name not unique: " + name); - - for (auto& client : m_clients) - { - if (&client->context() == &context) - { - client->name = std::move(name); - return; - } - } - throw runtime_error("no client for current context"); + client.m_name = std::move(name); } -String ClientManager::get_client_name(const Context& context) +Client& ClientManager::get_client(const Context& context) { for (auto& client : m_clients) { if (&client->context() == &context) - return client->name; + return *client; } throw runtime_error("no client for current context"); } -Context& ClientManager::get_client_context(const String& name) +Client& ClientManager::get_client(const String& name) { - auto it = find_if(m_clients, [&name](std::unique_ptr& client) - { return client->name == name; }); - if (it != m_clients.end()) - return (*it)->context(); + for (auto& client : m_clients) + { + if (client->m_name == name) + return *client; + } throw runtime_error("no client named: " + name); } diff --git a/src/client_manager.hh b/src/client_manager.hh index 06ead097..3c964b2c 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -9,14 +9,34 @@ namespace Kakoune struct client_removed{}; +class Client +{ +public: + Context& context() { return m_input_handler.context(); } + const String& name() const { return m_name; } + +private: + friend class ClientManager; + + Client(std::unique_ptr&& ui, + Window& window, String name); + Client(Client&&) = delete; + Client& operator=(Client&& other) = delete; + + const std::unique_ptr m_user_interface; + InputHandler m_input_handler; + String m_name; +}; + + class ClientManager : public Singleton { public: ClientManager(); ~ClientManager(); - void create_client(std::unique_ptr&& ui, - const String& init_cmd); + Client* create_client(std::unique_ptr&& ui, + const String& init_cmd); bool empty() const { return m_clients.empty(); } size_t count() const { return m_clients.size(); } @@ -26,14 +46,14 @@ public: void redraw_clients() const; - void set_client_name(Context& context, String name); - String get_client_name(const Context& context); - Context& get_client_context(const String& name); + Client& get_client(const Context& context); + Client& get_client(const String& name); + void set_client_name(Client& client, String name); + private: - void remove_client_by_context(Context& context); + void remove_client(Client& client); String generate_name() const; - struct Client; std::vector> m_clients; std::vector> m_windows; }; diff --git a/src/commands.cc b/src/commands.cc index df2fd74a..7a3fff0d 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -535,7 +535,7 @@ void context_wrap(const CommandParameters& params, Context& context, Func func) ParametersParser::Flags::None, 1); Context& real_context = parser.has_option("client") ? - ClientManager::instance().get_client_context(parser.option_value("client")) + ClientManager::instance().get_client(parser.option_value("client")).context() : context; if (parser.has_option("draft")) @@ -745,7 +745,8 @@ void set_client_name(const CommandParameters& params, Context& context) { ParametersParser parser(params, OptionMap{}, ParametersParser::Flags::None, 1, 1); - ClientManager::instance().set_client_name(context, params[0]); + auto& manager = ClientManager::instance(); + manager.set_client_name(manager.get_client(context), params[0]); } void set_register(const CommandParameters& params, Context& context) diff --git a/src/main.cc b/src/main.cc index 10809a0d..bd5b43b2 100644 --- a/src/main.cc +++ b/src/main.cc @@ -86,7 +86,7 @@ void register_env_vars() { return Server::instance().filename(); }); shell_manager.register_env_var("client", [](const String& name, const Context& context) - { return ClientManager::instance().get_client_name(context); }); + { return ClientManager::instance().get_client(context).name(); }); shell_manager.register_env_var("cursor_line", [](const String& name, const Context& context) { return int_to_str((int)context.editor().main_selection().last().line() + 1); });