Store the current client in context
This commit is contained in:
parent
a2aefa2998
commit
c1fcc593a1
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
59
src/main.cc
59
src/main.cc
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user