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
{
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,
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<UserInterface> 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<UserInterface>&& ui,
const String& init_commands)
Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& 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>& 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>& 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);
}

View File

@ -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<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>
{
public:
ClientManager();
~ClientManager();
void create_client(std::unique_ptr<UserInterface>&& ui,
const String& init_cmd);
Client* create_client(std::unique_ptr<UserInterface>&& 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<std::unique_ptr<Client>> m_clients;
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);
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)

View File

@ -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); });