From f76323f56e8d98ad5ae9f1b26f83689e008c8454 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 26 Sep 2012 14:13:04 +0200 Subject: [PATCH] Move UserInterface out of Client into Context --- src/client.cc | 83 ++++++++++++++++++------------------------- src/client.hh | 14 +++----- src/commands.cc | 11 +++--- src/context.hh | 27 ++++++++++---- src/main.cc | 20 +++++++---- src/user_interface.hh | 3 +- 6 files changed, 80 insertions(+), 78 deletions(-) diff --git a/src/client.cc b/src/client.cc index 3d9c61f4..f0ec7bb9 100644 --- a/src/client.cc +++ b/src/client.cc @@ -20,7 +20,6 @@ public: virtual void on_key(const Key& key, Context& context) = 0; protected: - UserInterface& ui() { return *m_client.m_ui; } void reset_normal_mode(); std::pair>& last_insert() { return m_client.m_last_insert; } private: @@ -67,16 +66,12 @@ void ClientMode::reset_normal_mode() class MenuMode : public ClientMode { public: - MenuMode(Client& client, const memoryview& choices, MenuCallback callback) - : ClientMode(client), + MenuMode(Context& context, const memoryview& choices, + MenuCallback callback) + : ClientMode(context.client()), m_callback(callback), m_choice_count(choices.size()), m_selected(0) { - ui().menu_show(choices); - } - - ~MenuMode() - { - ui().menu_hide(); + context.ui().menu_show(choices); } void on_key(const Key& key, Context& context) override @@ -88,7 +83,7 @@ public: { if (++m_selected >= m_choice_count) m_selected = 0; - ui().menu_select(m_selected); + context.ui().menu_select(m_selected); } if (key == Key::Up or key == Key::BackTab or @@ -97,10 +92,11 @@ public: { if (--m_selected < 0) m_selected = m_choice_count-1; - ui().menu_select(m_selected); + context.ui().menu_select(m_selected); } if (key == Key(Key::Modifiers::Control, 'm')) { + context.ui().menu_hide(); // save callback as reset_normal_mode will delete this MenuCallback callback = std::move(m_callback); int selected = m_selected; @@ -109,12 +105,13 @@ public: } if (key == Key::Escape) { + context.ui().menu_hide(); reset_normal_mode(); } if (key.modifiers == Key::Modifiers::None and key.key >= '0' and key.key <= '9') { - ui().menu_hide(); + context.ui().menu_hide(); // save callback as reset_normal_mode will delete this MenuCallback callback = std::move(m_callback); reset_normal_mode(); @@ -131,18 +128,13 @@ private: class PromptMode : public ClientMode { public: - PromptMode(Client& client, const String& prompt, + PromptMode(Context& context, const String& prompt, Completer completer, PromptCallback callback) - : ClientMode(client), m_prompt(prompt), + : ClientMode(context.client()), m_prompt(prompt), m_completer(completer), m_callback(callback) { m_history_it = ms_history[m_prompt].end(); - ui().print_status(m_prompt, m_prompt.length()); - } - - ~PromptMode() - { - ui().menu_hide(); + context.ui().print_status(m_prompt, m_prompt.length()); } void on_key(const Key& key, Context& context) override @@ -155,7 +147,8 @@ public: history.erase(it); history.push_back(m_result); - ui().print_status(""); + context.ui().print_status(""); + context.ui().menu_hide(); // save callback as reset_normal_mode will delete this PromptCallback callback = std::move(m_callback); String result = std::move(m_result); @@ -167,7 +160,8 @@ public: } else if (key == Key::Escape) { - ui().print_status(""); + context.ui().print_status(""); + context.ui().menu_hide(); reset_normal_mode(); return; } @@ -235,14 +229,14 @@ public: --m_cursor_pos; } - ui().menu_hide(); + context.ui().menu_hide(); m_current_completion = -1; } else if (key == Key(Key::Modifiers::Control, 'r')) { - Key k = ui().get_key(); + Key k = context.ui().get_key(); String reg = RegisterManager::instance()[k.key].values(context)[0]; - ui().menu_hide(); + context.ui().menu_hide(); m_current_completion = -1; m_result = m_result.substr(0, m_cursor_pos) + reg + m_result.substr(m_cursor_pos, String::npos); @@ -260,8 +254,8 @@ public: if (candidates.empty()) return; - ui().menu_hide(); - ui().menu_show(candidates); + context.ui().menu_hide(); + context.ui().menu_show(candidates); String prefix = m_result.substr(m_completions.start, m_completions.end - m_completions.start); if (not contains(candidates, prefix)) @@ -274,19 +268,19 @@ public: m_current_completion = candidates.size()-1; const String& completion = candidates[m_current_completion]; - ui().menu_select(m_current_completion); + context.ui().menu_select(m_current_completion); m_result = m_result.substr(0, m_completions.start) + completion + m_result.substr(m_cursor_pos); m_cursor_pos = m_completions.start + completion.length(); } else { - ui().menu_hide(); + context.ui().menu_hide(); m_current_completion = -1; m_result = m_result.substr(0, m_cursor_pos) + key.key + m_result.substr(m_cursor_pos, String::npos); ++m_cursor_pos; } - ui().print_status(m_prompt + m_result, m_prompt.length() + m_cursor_pos); + context.ui().print_status(m_prompt + m_result, m_prompt.length() + m_cursor_pos); } private: @@ -390,9 +384,8 @@ private: IncrementalInserter m_inserter; }; -Client::Client(UserInterface* ui) +Client::Client() : m_mode(new NormalMode(*this)), - m_ui(ui), m_last_insert(IncrementalInserter::Mode::Insert, {}) { } @@ -406,7 +399,7 @@ void Client::insert(Editor& editor, IncrementalInserter::Mode mode) m_mode.reset(new InsertMode(*this, editor, mode)); } -void Client::repeat_last_insert(Editor& editor, Context& context) +void Client::repeat_last_insert(Context& context) { if (m_last_insert.second.empty()) return; @@ -415,22 +408,24 @@ void Client::repeat_last_insert(Editor& editor, Context& context) swap(keys, m_last_insert.second); // m_last_insert will be refilled by the new InsertMode // this is very inefficient. - m_mode.reset(new InsertMode(*this, editor, m_last_insert.first)); + m_mode.reset(new InsertMode(*this, context.editor(), m_last_insert.first)); for (auto& key : keys) m_mode->on_key(key, context); assert(dynamic_cast(m_mode.get()) != nullptr); } void Client::prompt(const String& prompt, Completer completer, - PromptCallback callback) + PromptCallback callback, Context& context) { - m_mode.reset(new PromptMode(*this, prompt, completer, callback)); + assert(&context.client() == this); + m_mode.reset(new PromptMode(context, prompt, completer, callback)); } void Client::menu(const memoryview& choices, - MenuCallback callback) + MenuCallback callback, Context& context) { - m_mode.reset(new MenuMode(*this, choices, callback)); + assert(&context.client() == this); + m_mode.reset(new MenuMode(context, choices, callback)); } void Client::on_next_key(KeyCallback callback) @@ -440,18 +435,8 @@ void Client::on_next_key(KeyCallback callback) void Client::handle_next_input(Context& context) { - m_mode->on_key(m_ui->get_key(), context); + m_mode->on_key(context.ui().get_key(), context); context.draw_ifn(); } -void Client::print_status(const String& status, CharCount cursor_pos) -{ - m_ui->print_status(status, cursor_pos); -} - -void Client::draw_window(Window& window) -{ - m_ui->draw_window(window); -} - } diff --git a/src/client.hh b/src/client.hh index 2afd4590..27000ab4 100644 --- a/src/client.hh +++ b/src/client.hh @@ -6,13 +6,11 @@ #include "utils.hh" #include "string.hh" #include "window.hh" -#include "user_interface.hh" namespace Kakoune { class Editor; -class Window; class Context; using MenuCallback = std::function; @@ -24,20 +22,17 @@ class ClientMode; class Client : public SafeCountable { public: - Client(UserInterface* ui); + Client(); ~Client(); void insert(Editor& editor, IncrementalInserter::Mode mode); - void repeat_last_insert(Editor& editor, Context& context); + void repeat_last_insert(Context& context); void prompt(const String& prompt, Completer completer, - PromptCallback callback); + PromptCallback callback, Context& context); void menu(const memoryview& choices, - MenuCallback callback); - - void print_status(const String& status, CharCount cursor_pos = -1); - void draw_window(Window& window); + MenuCallback callback, Context& context); void on_next_key(KeyCallback callback); @@ -46,7 +41,6 @@ public: private: friend class ClientMode; std::unique_ptr m_mode; - std::unique_ptr m_ui; std::pair> m_last_insert; }; diff --git a/src/commands.cc b/src/commands.cc index 6211a1b7..dd06aa75 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -675,17 +675,18 @@ private: void exec_keys(const KeyList& keys, Context& context) { - BatchUI* batch_ui = new BatchUI(keys); - Client batch_client(batch_ui); - RegisterRestorer quote('"', context); RegisterRestorer slash('/', context); + BatchUI batch_ui(keys); + Client batch_client; + scoped_edition edition(context.editor()); Context new_context(batch_client); new_context.change_editor(context.editor()); - while (batch_ui->has_key_left()) + new_context.change_ui(batch_ui); + while (batch_ui.has_key_left()) batch_client.handle_next_input(new_context); } @@ -725,7 +726,7 @@ void menu(const CommandParameters& params, Context& context) [=](int choice, Context& context) { if (choice >= 0 and choice < commands.size()) CommandManager::instance().execute(commands[choice], context); - }); + }, context); } void try_catch(const CommandParameters& params, Context& context) diff --git a/src/context.hh b/src/context.hh index 4e2c5479..a30a16bc 100644 --- a/src/context.hh +++ b/src/context.hh @@ -3,6 +3,7 @@ #include "window.hh" #include "client.hh" +#include "user_interface.hh" namespace Kakoune { @@ -56,11 +57,24 @@ struct Context } bool has_client() const { return m_client; } + UserInterface& ui() const + { + if (not has_ui()) + throw runtime_error("no user interface in context"); + return *m_ui; + } + bool has_ui() const { return m_ui; } + void change_editor(Editor& editor) { m_editor.reset(&editor); } + void change_ui(UserInterface& ui) + { + m_ui.reset(&ui); + } + OptionManager& option_manager() const { if (has_window()) @@ -72,22 +86,23 @@ struct Context void draw_ifn() const { - if (has_client() and has_window()) - client().draw_window(window()); + if (has_ui() and has_window()) + ui().draw_window(window()); } void print_status(const String& status) const { - if (has_client()) - client().print_status(status); + if (has_ui()) + ui().print_status(status); } int numeric_param() const { return m_numeric_param; } void numeric_param(int param) { m_numeric_param = param; } public: - safe_ptr m_editor; - safe_ptr m_client; + safe_ptr m_editor; + safe_ptr m_client; + safe_ptr m_ui; int m_numeric_param = 0; }; diff --git a/src/main.cc b/src/main.cc index 8a771b7b..494d6406 100644 --- a/src/main.cc +++ b/src/main.cc @@ -41,7 +41,7 @@ void do_insert(Context& context) void do_repeat_insert(Context& context) { - context.client().repeat_last_insert(context.editor(), context); + context.client().repeat_last_insert(context); } template @@ -98,7 +98,8 @@ void do_command(Context& context) { context.client().prompt( ":", std::bind(&CommandManager::complete, &CommandManager::instance(), _1, _2, _3), - [](const String& cmdline, Context& context) { CommandManager::instance().execute(cmdline, context); }); + [](const String& cmdline, Context& context) { CommandManager::instance().execute(cmdline, context); }, + context); } void do_pipe(Context& context) @@ -112,7 +113,7 @@ void do_pipe(Context& context) strings.push_back(ShellManager::instance().pipe(String(sel.begin(), sel.end()), cmdline, context, {}, {})); editor.replace(strings); - }); + }, context); } @@ -128,7 +129,7 @@ void do_search(Context& context) RegisterManager::instance()['/'] = ex; context.editor().select(std::bind(select_next_match, _1, ex), mode); - }); + }, context); } template @@ -195,14 +196,16 @@ void do_select_regex(Context& context) { context.client().prompt("select: ", complete_nothing, [](const String& ex, Context& context) - { context.editor().multi_select(std::bind(select_all_matches, _1, ex)); }); + { context.editor().multi_select(std::bind(select_all_matches, _1, ex)); }, + context); } void do_split_regex(Context& context) { context.client().prompt("select: ", complete_nothing, [](const String& ex, Context& context) - { context.editor().multi_select(std::bind(split_selection, _1, ex)); }); + { context.editor().multi_select(std::bind(split_selection, _1, ex)); }, + context); } void do_join(Context& context) @@ -475,8 +478,11 @@ int main(int argc, char* argv[]) try { - Client client(new NCursesUI()); + Client client; + NCursesUI ui; + Context context(client); + context.change_ui(ui); try { diff --git a/src/user_interface.hh b/src/user_interface.hh index 1b490b22..a6df5ec2 100644 --- a/src/user_interface.hh +++ b/src/user_interface.hh @@ -4,6 +4,7 @@ #include "memoryview.hh" #include "keys.hh" #include "units.hh" +#include "utils.hh" namespace Kakoune { @@ -11,7 +12,7 @@ namespace Kakoune class String; class Window; -class UserInterface +class UserInterface : public SafeCountable { public: virtual ~UserInterface() {}