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 "completion.hh"
#include "utils.hh"
namespace Kakoune
{
@ -12,26 +13,20 @@ class Window;
class String;
class Context;
class Client
class Client : public SafeCountable
{
public:
virtual ~Client() {}
virtual void draw_window(Window& window) = 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;
};
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

View File

@ -214,7 +214,7 @@ private:
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;
try
@ -223,7 +223,7 @@ Buffer* open_or_create(const String& filename)
}
catch (file_not_found& what)
{
print_status("new file " + filename);
context.print_status("new file " + filename);
buffer = new Buffer(filename, Buffer::Type::NewFile);
}
return buffer;
@ -248,7 +248,7 @@ void edit(const CommandParameters& params, Context& context)
if (parser.has_option("scratch"))
buffer = new Buffer(filename, Buffer::Type::Scratch);
else
buffer = open_or_create(filename);
buffer = open_or_create(filename, context);
}
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}));
}
context = Context(window);
context.change_editor(window);
}
void write_buffer(const CommandParameters& params, Context& context)
@ -344,7 +344,7 @@ void show_buffer(const CommandParameters& params, Context& context)
if (not buffer)
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)
@ -374,7 +374,7 @@ void delete_buffer(const CommandParameters& params, Context& context)
{
if (buf != buffer)
{
context = Context(*buf->get_or_create_window());
context.change_editor(*buf->get_or_create_window());
break;
}
}
@ -554,7 +554,7 @@ void echo_message(const CommandParameters& params, Context& context)
String message;
for (auto& param : params)
message += param + " ";
print_status(message);
context.print_status(message);
}
void exec_commands_in_file(const CommandParameters& params,
@ -626,16 +626,10 @@ private:
class BatchClient : public Client
{
public:
BatchClient(const KeyList& keys)
BatchClient(const KeyList& keys, Client* previous_client)
: m_keys(keys), m_pos(0)
{
m_previous_client = current_client;
current_client = this;
}
~BatchClient()
{
current_client = m_previous_client;
m_previous_client = previous_client;
}
String prompt(const String&, const Context&, Completer)
@ -679,7 +673,8 @@ private:
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 slash('/', context);
@ -687,7 +682,8 @@ void exec_keys(const KeyList& keys, Context& context)
scoped_edition edition(context.editor());
int count = 0;
Context new_context(context);
Context new_context(batch_client);
new_context.change_editor(context.window());
while (batch_client.has_key_left())
{
Key key = batch_client.get_key();
@ -738,7 +734,8 @@ void menu(const CommandParameters& params, Context& context)
}
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);
if (i > 0 and i < (count / 2) + 1)

View File

@ -2,22 +2,26 @@
#define context_hh_INCLUDED
#include "window.hh"
#include "client.hh"
namespace Kakoune
{
class Buffer;
struct Context
{
Context() {}
Context(Editor& editor)
: m_editor(&editor) {}
Context(Client& client)
: m_client(&client) {}
// to allow func(Context(Editor(...)))
Context(Editor&& editor)
: m_editor(&editor) {}
Context& operator=(const Context&) = delete;
Buffer& buffer() const
{
if (not has_buffer())
@ -42,6 +46,21 @@ struct Context
}
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
{
if (has_window())
@ -51,11 +70,24 @@ struct Context
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; }
void numeric_param(int param) { m_numeric_param = param; }
public:
safe_ptr<Editor> m_editor;
safe_ptr<Client> m_client;
int m_numeric_param = 0;
};

View File

@ -97,12 +97,12 @@ void do_insert(Context& context)
last_insert_sequence.mode = mode;
last_insert_sequence.keys.clear();
IncrementalInserter inserter(context.editor(), mode);
draw_editor_ifn(context.editor());
context.draw_ifn();
insert_sequence(inserter, context,
[&]() { Key key = get_key();
[&]() { Key key = context.client().get_key();
last_insert_sequence.keys.push_back(key);
return key; },
[&]() { draw_editor_ifn(context.editor()); });
[&]() { context.draw_ifn(); });
}
void do_repeat_insert(Context& context)
@ -131,7 +131,7 @@ void do_go(Context& context)
}
else
{
Key key = get_key();
Key key = context.client().get_key();
if (key.modifiers != Key::Modifiers::None)
return;
@ -168,8 +168,8 @@ void do_command(Context& context)
{
try
{
auto cmdline = prompt(":", context,
std::bind(&CommandManager::complete,
auto cmdline = context.client().prompt(
":", context, std::bind(&CommandManager::complete,
&CommandManager::instance(),
_1, _2, _3));
@ -182,7 +182,7 @@ void do_pipe(Context& context)
{
try
{
auto cmdline = prompt("|", context, complete_nothing);
auto cmdline = context.client().prompt("|", context, complete_nothing);
Editor& editor = context.editor();
std::vector<String> strings;
@ -199,7 +199,7 @@ void do_search(Context& context)
{
try
{
String ex = prompt("/", context);
String ex = context.client().prompt("/", context);
if (ex.empty())
ex = RegisterManager::instance()['/'].values(context)[0];
else
@ -217,7 +217,7 @@ void do_search_next(Context& context)
if (not ex.empty())
context.editor().select(std::bind(select_next_match, _1, ex), append);
else
print_status("no search pattern");
context.print_status("no search pattern");
}
void do_yank(Context& context)
@ -274,7 +274,7 @@ void do_select_regex(Context& context)
{
try
{
String ex = prompt("select: ", context);
String ex = context.client().prompt("select: ", context);
context.editor().multi_select(std::bind(select_all_matches, _1, ex));
}
catch (prompt_aborted&) {}
@ -284,7 +284,7 @@ void do_split_regex(Context& context)
{
try
{
String ex = prompt("split: ", context);
String ex = context.client().prompt("split: ", context);
context.editor().multi_select(std::bind(split_selection, _1, ex));
}
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 key = get_key();
Key key = context.client().get_key();
auto it = key_to_selector.find(key);
if (it != key_to_selector.end())
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, '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, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, 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, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to, _1, get_key().key, context.numeric_param(), true), true); } },
{ { 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, context.client().get_key().key, context.numeric_param(), 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, context.client().get_key().key, context.numeric_param(), true), true); } },
{ { Key::Modifiers::None, 'd' }, do_erase },
{ { 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<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().redo()) { print_status("nothing left to redo"); } }) },
{ { 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()) { context.print_status("nothing left to redo"); } }) },
{ { Key::Modifiers::Alt, 'i' }, do_select_object<true> },
{ { 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, 'f' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, 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, 'F' }, [](Context& context) { context.editor().select(std::bind(select_to_reverse, _1, get_key().key, context.numeric_param(), true), 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)); } },
{ { 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, 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, 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, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) },
@ -480,8 +480,7 @@ int main(int argc, char* argv[])
try
{
NCursesClient client;
current_client = &client;
Context context;
Context context(client);
try
{
@ -489,7 +488,7 @@ int main(int argc, char* argv[])
}
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
{
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;
while(not quit_requested)
{
try
{
Key key = get_key();
Key key = context.client().get_key();
if (key.modifiers == Key::Modifiers::None and isdigit(key.key))
count = count * 10 + key.key - '0';
else
@ -525,14 +524,14 @@ int main(int argc, char* argv[])
{
context.numeric_param(count);
it->second(context);
current_client->draw_window(context.window());
context.draw_ifn();
}
count = 0;
}
}
catch (Kakoune::runtime_error& error)
{
print_status(error.description());
context.print_status(error.description());
}
}
}