Store the current client in context

This commit is contained in:
Maxime Coste 2012-08-15 22:36:45 +02:00
parent a2aefa2998
commit c1fcc593a1
5 changed files with 84 additions and 96 deletions

View File

@ -1,35 +0,0 @@
#include "client.hh"
#include "window.hh"
namespace Kakoune
{
Client* current_client = nullptr;
void draw_editor_ifn(Editor& editor)
{
Window* window = dynamic_cast<Window*>(&editor);
if (current_client and window)
current_client->draw_window(*window);
}
String prompt(const String& text, const Context& context, Completer completer)
{
assert(current_client);
return current_client->prompt(text, context, completer);
}
Key get_key()
{
assert(current_client);
return current_client->get_key();
}
void print_status(const String& status)
{
assert(current_client);
return current_client->print_status(status);
}
}

View File

@ -3,6 +3,7 @@
#include "keys.hh" #include "keys.hh"
#include "completion.hh" #include "completion.hh"
#include "utils.hh"
namespace Kakoune namespace Kakoune
{ {
@ -12,26 +13,20 @@ class Window;
class String; class String;
class Context; class Context;
class Client class Client : public SafeCountable
{ {
public: public:
virtual ~Client() {} virtual ~Client() {}
virtual void draw_window(Window& window) = 0; virtual void draw_window(Window& window) = 0;
virtual void print_status(const String& status) = 0; virtual void print_status(const String& status) = 0;
virtual String prompt(const String& prompt, const Context& context, Completer completer) = 0; virtual String prompt(const String& prompt, const Context& context,
Completer completer = complete_nothing) = 0;
virtual Key get_key() = 0; virtual Key get_key() = 0;
}; };
struct prompt_aborted {}; struct prompt_aborted {};
extern Client* current_client;
void draw_editor_ifn(Editor& editor);
String prompt(const String& text, const Context& context, Completer completer = complete_nothing);
Key get_key();
void print_status(const String& status);
} }
#endif // client_hh_INCLUDED #endif // client_hh_INCLUDED

View File

@ -214,7 +214,7 @@ private:
std::unordered_map<String, bool> m_options; std::unordered_map<String, bool> m_options;
}; };
Buffer* open_or_create(const String& filename) Buffer* open_or_create(const String& filename, Context& context)
{ {
Buffer* buffer = NULL; Buffer* buffer = NULL;
try try
@ -223,7 +223,7 @@ Buffer* open_or_create(const String& filename)
} }
catch (file_not_found& what) catch (file_not_found& what)
{ {
print_status("new file " + filename); context.print_status("new file " + filename);
buffer = new Buffer(filename, Buffer::Type::NewFile); buffer = new Buffer(filename, Buffer::Type::NewFile);
} }
return buffer; return buffer;
@ -248,7 +248,7 @@ void edit(const CommandParameters& params, Context& context)
if (parser.has_option("scratch")) if (parser.has_option("scratch"))
buffer = new Buffer(filename, Buffer::Type::Scratch); buffer = new Buffer(filename, Buffer::Type::Scratch);
else else
buffer = open_or_create(filename); buffer = open_or_create(filename, context);
} }
Window& window = *buffer->get_or_create_window(); Window& window = *buffer->get_or_create_window();
@ -262,7 +262,7 @@ void edit(const CommandParameters& params, Context& context)
window.select(window.buffer().iterator_at({line, column})); window.select(window.buffer().iterator_at({line, column}));
} }
context = Context(window); context.change_editor(window);
} }
void write_buffer(const CommandParameters& params, Context& context) void write_buffer(const CommandParameters& params, Context& context)
@ -344,7 +344,7 @@ void show_buffer(const CommandParameters& params, Context& context)
if (not buffer) if (not buffer)
throw runtime_error("buffer " + buffer_name + " does not exists"); throw runtime_error("buffer " + buffer_name + " does not exists");
context = Context(*buffer->get_or_create_window()); context.change_editor(*buffer->get_or_create_window());
} }
void delete_buffer(const CommandParameters& params, Context& context) void delete_buffer(const CommandParameters& params, Context& context)
@ -374,7 +374,7 @@ void delete_buffer(const CommandParameters& params, Context& context)
{ {
if (buf != buffer) if (buf != buffer)
{ {
context = Context(*buf->get_or_create_window()); context.change_editor(*buf->get_or_create_window());
break; break;
} }
} }
@ -554,7 +554,7 @@ void echo_message(const CommandParameters& params, Context& context)
String message; String message;
for (auto& param : params) for (auto& param : params)
message += param + " "; message += param + " ";
print_status(message); context.print_status(message);
} }
void exec_commands_in_file(const CommandParameters& params, void exec_commands_in_file(const CommandParameters& params,
@ -626,16 +626,10 @@ private:
class BatchClient : public Client class BatchClient : public Client
{ {
public: public:
BatchClient(const KeyList& keys) BatchClient(const KeyList& keys, Client* previous_client)
: m_keys(keys), m_pos(0) : m_keys(keys), m_pos(0)
{ {
m_previous_client = current_client; m_previous_client = previous_client;
current_client = this;
}
~BatchClient()
{
current_client = m_previous_client;
} }
String prompt(const String&, const Context&, Completer) String prompt(const String&, const Context&, Completer)
@ -679,7 +673,8 @@ private:
void exec_keys(const KeyList& keys, Context& context) void exec_keys(const KeyList& keys, Context& context)
{ {
BatchClient batch_client(keys); BatchClient batch_client(keys, context.has_client() ? &context.client()
: nullptr);
RegisterRestorer quote('"', context); RegisterRestorer quote('"', context);
RegisterRestorer slash('/', context); RegisterRestorer slash('/', context);
@ -687,7 +682,8 @@ void exec_keys(const KeyList& keys, Context& context)
scoped_edition edition(context.editor()); scoped_edition edition(context.editor());
int count = 0; int count = 0;
Context new_context(context); Context new_context(batch_client);
new_context.change_editor(context.window());
while (batch_client.has_key_left()) while (batch_client.has_key_left())
{ {
Key key = batch_client.get_key(); Key key = batch_client.get_key();
@ -738,7 +734,8 @@ void menu(const CommandParameters& params, Context& context)
} }
oss << "(empty cancels): "; oss << "(empty cancels): ";
String choice = prompt(oss.str(), context, complete_nothing); String choice = context.client().prompt(oss.str(), context,
complete_nothing);
int i = str_to_int(choice); int i = str_to_int(choice);
if (i > 0 and i < (count / 2) + 1) if (i > 0 and i < (count / 2) + 1)

View File

@ -2,22 +2,26 @@
#define context_hh_INCLUDED #define context_hh_INCLUDED
#include "window.hh" #include "window.hh"
#include "client.hh"
namespace Kakoune namespace Kakoune
{ {
class Buffer;
struct Context struct Context
{ {
Context() {} Context() {}
Context(Editor& editor) Context(Editor& editor)
: m_editor(&editor) {} : m_editor(&editor) {}
Context(Client& client)
: m_client(&client) {}
// to allow func(Context(Editor(...))) // to allow func(Context(Editor(...)))
Context(Editor&& editor) Context(Editor&& editor)
: m_editor(&editor) {} : m_editor(&editor) {}
Context& operator=(const Context&) = delete;
Buffer& buffer() const Buffer& buffer() const
{ {
if (not has_buffer()) if (not has_buffer())
@ -42,6 +46,21 @@ struct Context
} }
bool has_window() const { return m_editor and dynamic_cast<Window*>(m_editor.get()); } bool has_window() const { return m_editor and dynamic_cast<Window*>(m_editor.get()); }
Client& client() const
{
if (not has_client())
throw runtime_error("no client in context");
return *m_client;
}
bool has_client() const { return m_client; }
void change_editor(Editor& editor)
{
if (has_client() and not dynamic_cast<Window*>(&editor))
throw logic_error();
m_editor.reset(&editor);
}
OptionManager& option_manager() const OptionManager& option_manager() const
{ {
if (has_window()) if (has_window())
@ -51,11 +70,24 @@ struct Context
return GlobalOptionManager::instance(); return GlobalOptionManager::instance();
} }
void draw_ifn() const
{
if (has_client())
client().draw_window(window());
}
void print_status(const String& status) const
{
if (has_client())
client().print_status(status);
}
int numeric_param() const { return m_numeric_param; } int numeric_param() const { return m_numeric_param; }
void numeric_param(int param) { m_numeric_param = param; } void numeric_param(int param) { m_numeric_param = param; }
public: public:
safe_ptr<Editor> m_editor; safe_ptr<Editor> m_editor;
safe_ptr<Client> m_client;
int m_numeric_param = 0; int m_numeric_param = 0;
}; };

View File

@ -97,12 +97,12 @@ void do_insert(Context& context)
last_insert_sequence.mode = mode; last_insert_sequence.mode = mode;
last_insert_sequence.keys.clear(); last_insert_sequence.keys.clear();
IncrementalInserter inserter(context.editor(), mode); IncrementalInserter inserter(context.editor(), mode);
draw_editor_ifn(context.editor()); context.draw_ifn();
insert_sequence(inserter, context, insert_sequence(inserter, context,
[&]() { Key key = get_key(); [&]() { Key key = context.client().get_key();
last_insert_sequence.keys.push_back(key); last_insert_sequence.keys.push_back(key);
return key; }, return key; },
[&]() { draw_editor_ifn(context.editor()); }); [&]() { context.draw_ifn(); });
} }
void do_repeat_insert(Context& context) void do_repeat_insert(Context& context)
@ -131,7 +131,7 @@ void do_go(Context& context)
} }
else else
{ {
Key key = get_key(); Key key = context.client().get_key();
if (key.modifiers != Key::Modifiers::None) if (key.modifiers != Key::Modifiers::None)
return; return;
@ -168,8 +168,8 @@ void do_command(Context& context)
{ {
try try
{ {
auto cmdline = prompt(":", context, auto cmdline = context.client().prompt(
std::bind(&CommandManager::complete, ":", context, std::bind(&CommandManager::complete,
&CommandManager::instance(), &CommandManager::instance(),
_1, _2, _3)); _1, _2, _3));
@ -182,7 +182,7 @@ void do_pipe(Context& context)
{ {
try try
{ {
auto cmdline = prompt("|", context, complete_nothing); auto cmdline = context.client().prompt("|", context, complete_nothing);
Editor& editor = context.editor(); Editor& editor = context.editor();
std::vector<String> strings; std::vector<String> strings;
@ -199,7 +199,7 @@ void do_search(Context& context)
{ {
try try
{ {
String ex = prompt("/", context); String ex = context.client().prompt("/", context);
if (ex.empty()) if (ex.empty())
ex = RegisterManager::instance()['/'].values(context)[0]; ex = RegisterManager::instance()['/'].values(context)[0];
else else
@ -217,7 +217,7 @@ void do_search_next(Context& context)
if (not ex.empty()) if (not ex.empty())
context.editor().select(std::bind(select_next_match, _1, ex), append); context.editor().select(std::bind(select_next_match, _1, ex), append);
else else
print_status("no search pattern"); context.print_status("no search pattern");
} }
void do_yank(Context& context) void do_yank(Context& context)
@ -274,7 +274,7 @@ void do_select_regex(Context& context)
{ {
try try
{ {
String ex = prompt("select: ", context); String ex = context.client().prompt("select: ", context);
context.editor().multi_select(std::bind(select_all_matches, _1, ex)); context.editor().multi_select(std::bind(select_all_matches, _1, ex));
} }
catch (prompt_aborted&) {} catch (prompt_aborted&) {}
@ -284,7 +284,7 @@ void do_split_regex(Context& context)
{ {
try try
{ {
String ex = prompt("split: ", context); String ex = context.client().prompt("split: ", context);
context.editor().multi_select(std::bind(split_selection, _1, ex)); context.editor().multi_select(std::bind(split_selection, _1, ex));
} }
catch (prompt_aborted&) {} catch (prompt_aborted&) {}
@ -321,7 +321,7 @@ void do_select_object(Context& context)
{ { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _1, inner) }, { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _1, inner) },
}; };
Key key = get_key(); Key key = context.client().get_key();
auto it = key_to_selector.find(key); auto it = key_to_selector.find(key);
if (it != key_to_selector.end()) if (it != key_to_selector.end())
context.editor().select(it->second); context.editor().select(it->second);
@ -357,10 +357,10 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
{ { Key::Modifiers::None, 'K' }, [](Context& context) { context.editor().move_selections(BufferCoord(-std::max(context.numeric_param(),1), 0), true); } }, { { Key::Modifiers::None, 'K' }, [](Context& context) { context.editor().move_selections(BufferCoord(-std::max(context.numeric_param(),1), 0), true); } },
{ { Key::Modifiers::None, 'L' }, [](Context& context) { context.editor().move_selections(BufferCoord(0, std::max(context.numeric_param(),1)), true); } }, { { Key::Modifiers::None, 'L' }, [](Context& context) { context.editor().move_selections(BufferCoord(0, std::max(context.numeric_param(),1)), true); } },
{ { Key::Modifiers::None, 't' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, get_key().key, context.numeric_param(), false)); } }, { { Key::Modifiers::None, 't' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, context.client().get_key().key, context.numeric_param(), false)); } },
{ { Key::Modifiers::None, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, get_key().key, context.numeric_param(), true)); } }, { { Key::Modifiers::None, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, context.client().get_key().key, context.numeric_param(), true)); } },
{ { Key::Modifiers::None, 'T' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, get_key().key, context.numeric_param(), false), true); } }, { { Key::Modifiers::None, 'T' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, context.client().get_key().key, context.numeric_param(), false), true); } },
{ { Key::Modifiers::None, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, get_key().key, context.numeric_param(), true), true); } }, { { Key::Modifiers::None, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, context.client().get_key().key, context.numeric_param(), true), true); } },
{ { Key::Modifiers::None, 'd' }, do_erase }, { { Key::Modifiers::None, 'd' }, do_erase },
{ { Key::Modifiers::None, 'c' }, do_change }, { { Key::Modifiers::None, 'c' }, do_change },
@ -410,16 +410,16 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
{ { Key::Modifiers::None, 'n' }, do_search_next<false> }, { { Key::Modifiers::None, 'n' }, do_search_next<false> },
{ { Key::Modifiers::None, 'N' }, do_search_next<true> }, { { Key::Modifiers::None, 'N' }, do_search_next<true> },
{ { Key::Modifiers::None, 'u' }, repeated([](Context& context) { if (not context.editor().undo()) { print_status("nothing left to undo"); } }) }, { { Key::Modifiers::None, 'u' }, repeated([](Context& context) { if (not context.editor().undo()) { context.print_status("nothing left to undo"); } }) },
{ { Key::Modifiers::None, 'U' }, repeated([](Context& context) { if (not context.editor().redo()) { print_status("nothing left to redo"); } }) }, { { Key::Modifiers::None, 'U' }, repeated([](Context& context) { if (not context.editor().redo()) { context.print_status("nothing left to redo"); } }) },
{ { Key::Modifiers::Alt, 'i' }, do_select_object<true> }, { { Key::Modifiers::Alt, 'i' }, do_select_object<true> },
{ { Key::Modifiers::Alt, 'a' }, do_select_object<false> }, { { Key::Modifiers::Alt, 'a' }, do_select_object<false> },
{ { Key::Modifiers::Alt, 't' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, get_key().key, context.numeric_param(), false)); } }, { { Key::Modifiers::Alt, 't' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, context.client().get_key().key, context.numeric_param(), false)); } },
{ { Key::Modifiers::Alt, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, get_key().key, context.numeric_param(), true)); } }, { { Key::Modifiers::Alt, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, context.client().get_key().key, context.numeric_param(), true)); } },
{ { Key::Modifiers::Alt, 'T' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, get_key().key, context.numeric_param(), false), true); } }, { { Key::Modifiers::Alt, 'T' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, context.client().get_key().key, context.numeric_param(), false), true); } },
{ { Key::Modifiers::Alt, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, get_key().key, context.numeric_param(), true), true); } }, { { Key::Modifiers::Alt, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, context.client().get_key().key, context.numeric_param(), true), true); } },
{ { Key::Modifiers::Alt, 'w' }, repeated([](Context& context) { context.editor().select(select_to_next_word<true>); }) }, { { Key::Modifiers::Alt, 'w' }, repeated([](Context& context) { context.editor().select(select_to_next_word<true>); }) },
{ { Key::Modifiers::Alt, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) }, { { Key::Modifiers::Alt, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) },
@ -480,8 +480,7 @@ int main(int argc, char* argv[])
try try
{ {
NCursesClient client; NCursesClient client;
current_client = &client; Context context(client);
Context context;
try try
{ {
@ -489,7 +488,7 @@ int main(int argc, char* argv[])
} }
catch (Kakoune::runtime_error& error) catch (Kakoune::runtime_error& error)
{ {
print_status(error.description()); context.print_status(error.description());
} }
@ -506,16 +505,16 @@ int main(int argc, char* argv[])
else else
{ {
auto buffer = new Buffer("*scratch*", Buffer::Type::Scratch); auto buffer = new Buffer("*scratch*", Buffer::Type::Scratch);
context = Context(*buffer->get_or_create_window()); context.change_editor(*buffer->get_or_create_window());
} }
current_client->draw_window(context.window()); context.draw_ifn();
int count = 0; int count = 0;
while(not quit_requested) while(not quit_requested)
{ {
try try
{ {
Key key = get_key(); Key key = context.client().get_key();
if (key.modifiers == Key::Modifiers::None and isdigit(key.key)) if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
count = count * 10 + key.key - '0'; count = count * 10 + key.key - '0';
else else
@ -525,14 +524,14 @@ int main(int argc, char* argv[])
{ {
context.numeric_param(count); context.numeric_param(count);
it->second(context); it->second(context);
current_client->draw_window(context.window()); context.draw_ifn();
} }
count = 0; count = 0;
} }
} }
catch (Kakoune::runtime_error& error) catch (Kakoune::runtime_error& error)
{ {
print_status(error.description()); context.print_status(error.description());
} }
} }
} }