move Client as a public class instead of a ClientManager implementation detail

This commit is contained in:
Maxime Coste 2013-04-15 14:28:21 +02:00
parent 385241d2c0
commit cc91a71a96
4 changed files with 74 additions and 68 deletions

View File

@ -11,26 +11,15 @@
namespace Kakoune namespace Kakoune
{ {
struct ClientManager::Client Client::Client(std::unique_ptr<UserInterface>&& 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<UserInterface>&& ui, Window& window, kak_assert(not m_name.empty());
String name) context().change_editor(window);
: 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<UserInterface> user_interface;
InputHandler input_handler;
String name;
};
ClientManager::ClientManager() = default; ClientManager::ClientManager() = default;
ClientManager::~ClientManager() = default; ClientManager::~ClientManager() = default;
@ -43,7 +32,7 @@ String ClientManager::generate_name() const
bool found = false; bool found = false;
for (auto& client : m_clients) for (auto& client : m_clients)
{ {
if (client->name == name) if (client->m_name == name)
{ {
found = true; found = true;
break; break;
@ -54,53 +43,57 @@ String ClientManager::generate_name() const
} }
} }
void ClientManager::create_client(std::unique_ptr<UserInterface>&& ui, Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
const String& init_commands) const String& init_commands)
{ {
Buffer& buffer = **BufferManager::instance().begin(); Buffer& buffer = **BufferManager::instance().begin();
m_clients.emplace_back(new Client{std::move(ui), get_unused_window_for_buffer(buffer), Client* client = new Client{std::move(ui), get_unused_window_for_buffer(buffer),
generate_name()}); generate_name()};
Context* context = &m_clients.back()->context(); m_clients.emplace_back(client);
try try
{ {
CommandManager::instance().execute(init_commands, *context); CommandManager::instance().execute(init_commands, client->context());
} }
catch (Kakoune::runtime_error& error) catch (Kakoune::runtime_error& error)
{ {
context->print_status({ error.what(), get_color("Error") }); client->context().print_status({ error.what(), get_color("Error") });
context->hooks().run_hook("RuntimeError", error.what(), *context); client->context().hooks().run_hook("RuntimeError", error.what(),
client->context());
} }
catch (Kakoune::client_removed&) catch (Kakoune::client_removed&)
{ {
m_clients.pop_back(); m_clients.pop_back();
return; return nullptr;
} }
context->ui().set_input_callback([context, this]() { client->m_user_interface->set_input_callback([client, this]() {
try try
{ {
context->input_handler().handle_available_inputs(); client->m_input_handler.handle_available_inputs();
context->window().forget_timestamp(); client->context().window().forget_timestamp();
} }
catch (Kakoune::runtime_error& error) catch (Kakoune::runtime_error& error)
{ {
context->print_status({ error.what(), get_color("Error") }); client->context().print_status({ error.what(), get_color("Error") });
context->hooks().run_hook("RuntimeError", error.what(), *context); client->context().hooks().run_hook("RuntimeError", error.what(),
client->context());
} }
catch (Kakoune::client_removed&) catch (Kakoune::client_removed&)
{ {
ClientManager::instance().remove_client_by_context(*context); ClientManager::instance().remove_client(*client);
} }
ClientManager::instance().redraw_clients(); ClientManager::instance().redraw_clients();
}); });
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) for (auto it = m_clients.begin(); it != m_clients.end(); ++it)
{ {
if (&(*it)->context() == &context) if (it->get() == &client)
{ {
m_clients.erase(it); m_clients.erase(it);
return; return;
@ -139,7 +132,7 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
continue; continue;
if (client->context().editor().is_editing()) 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() + '\''); buffer.display_name() + '\'');
// change client context to edit the first buffer which is not the // 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()); 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>& client) auto it = find_if(m_clients, [&name](std::unique_ptr<Client>& client)
{ return client->name == name; }); { return client->m_name == name; });
if (it != m_clients.end() and &(*it)->context() != &context) if (it != m_clients.end() and it->get() != &client)
throw runtime_error("name not unique: " + name); throw runtime_error("name not unique: " + name);
client.m_name = std::move(name);
for (auto& client : m_clients)
{
if (&client->context() == &context)
{
client->name = std::move(name);
return;
}
}
throw runtime_error("no client for current context");
} }
String ClientManager::get_client_name(const Context& context) Client& ClientManager::get_client(const Context& context)
{ {
for (auto& client : m_clients) for (auto& client : m_clients)
{ {
if (&client->context() == &context) if (&client->context() == &context)
return client->name; return *client;
} }
throw runtime_error("no client for current context"); 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>& client) for (auto& client : m_clients)
{ return client->name == name; }); {
if (it != m_clients.end()) if (client->m_name == name)
return (*it)->context(); return *client;
}
throw runtime_error("no client named: " + name); throw runtime_error("no client named: " + name);
} }

View File

@ -9,14 +9,34 @@ namespace Kakoune
struct client_removed{}; 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<UserInterface>&& ui,
Window& window, String name);
Client(Client&&) = delete;
Client& operator=(Client&& other) = delete;
const std::unique_ptr<UserInterface> m_user_interface;
InputHandler m_input_handler;
String m_name;
};
class ClientManager : public Singleton<ClientManager> class ClientManager : public Singleton<ClientManager>
{ {
public: public:
ClientManager(); ClientManager();
~ClientManager(); ~ClientManager();
void create_client(std::unique_ptr<UserInterface>&& ui, Client* create_client(std::unique_ptr<UserInterface>&& ui,
const String& init_cmd); const String& init_cmd);
bool empty() const { return m_clients.empty(); } bool empty() const { return m_clients.empty(); }
size_t count() const { return m_clients.size(); } size_t count() const { return m_clients.size(); }
@ -26,14 +46,14 @@ public:
void redraw_clients() const; void redraw_clients() const;
void set_client_name(Context& context, String name); Client& get_client(const Context& context);
String get_client_name(const Context& context); Client& get_client(const String& name);
Context& get_client_context(const String& name); void set_client_name(Client& client, String name);
private: private:
void remove_client_by_context(Context& context); void remove_client(Client& client);
String generate_name() const; String generate_name() const;
struct Client;
std::vector<std::unique_ptr<Client>> m_clients; std::vector<std::unique_ptr<Client>> m_clients;
std::vector<std::unique_ptr<Window>> m_windows; std::vector<std::unique_ptr<Window>> m_windows;
}; };

View File

@ -535,7 +535,7 @@ void context_wrap(const CommandParameters& params, Context& context, Func func)
ParametersParser::Flags::None, 1); ParametersParser::Flags::None, 1);
Context& real_context = parser.has_option("client") ? 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; : context;
if (parser.has_option("draft")) if (parser.has_option("draft"))
@ -745,7 +745,8 @@ void set_client_name(const CommandParameters& params, Context& context)
{ {
ParametersParser parser(params, OptionMap{}, ParametersParser parser(params, OptionMap{},
ParametersParser::Flags::None, 1, 1); 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) void set_register(const CommandParameters& params, Context& context)

View File

@ -86,7 +86,7 @@ void register_env_vars()
{ return Server::instance().filename(); }); { return Server::instance().filename(); });
shell_manager.register_env_var("client", shell_manager.register_env_var("client",
[](const String& name, const Context& context) [](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", shell_manager.register_env_var("cursor_line",
[](const String& name, const Context& context) [](const String& name, const Context& context)
{ return int_to_str((int)context.editor().main_selection().last().line() + 1); }); { return int_to_str((int)context.editor().main_selection().last().line() + 1); });