From bf42d774696630650c6db3808770d4d8040781bc Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 5 Sep 2012 14:27:14 +0200 Subject: [PATCH] Handle inserting in Client::InsertMode --- src/client.cc | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/client.hh | 10 ++++-- src/main.cc | 80 ++---------------------------------------------- 3 files changed, 92 insertions(+), 82 deletions(-) diff --git a/src/client.cc b/src/client.cc index 1ed9299c..2be77de5 100644 --- a/src/client.cc +++ b/src/client.cc @@ -309,9 +309,89 @@ private: KeyCallback m_callback; }; -Client::Client() - : m_mode(new NormalMode(*this)) +class Client::InsertMode : public Client::Mode { +public: + InsertMode(Client& client, Editor& editor, IncrementalInserter::Mode mode) + : Client::Mode(client), m_inserter(editor, mode) + { + m_client.m_last_insert.first = mode; + m_client.m_last_insert.second.clear(); + } + + void on_key(const Key& key, Context& context) override + { + m_client.m_last_insert.second.push_back(key); + if (m_insert_reg) + { + if (key.modifiers == Key::Modifiers::None) + m_inserter.insert(RegisterManager::instance()[key.key].values(context)); + m_insert_reg = false; + return; + } + switch (key.modifiers) + { + case Key::Modifiers::None: + switch (key.key) + { + case 27: + m_client.reset_normal_mode(); + return; + default: + m_inserter.insert(String() + key.key); + } + break; + case Key::Modifiers::Control: + switch (key.key) + { + case 'r': + m_insert_reg = true; + break; + case 'm': + m_inserter.insert(String() + '\n'); + break; + case 'i': + m_inserter.insert(String() + '\t'); + break; + case 'd': + m_inserter.move_cursors({0, -1}); + break; + case 'e': + m_inserter.move_cursors({0, 1}); + break; + case 'g': + m_inserter.erase(); + break; + } + break; + } + } +private: + bool m_insert_reg = false; + IncrementalInserter m_inserter; +}; + +Client::Client() + : m_mode(new NormalMode(*this)), + m_last_insert(IncrementalInserter::Mode::Insert, {}) +{ +} + +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) +{ + std::vector keys; + 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)); + 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, diff --git a/src/client.hh b/src/client.hh index c31dd0a6..255df9e5 100644 --- a/src/client.hh +++ b/src/client.hh @@ -5,6 +5,7 @@ #include "completion.hh" #include "utils.hh" #include "string.hh" +#include "editor.hh" namespace Kakoune { @@ -36,6 +37,9 @@ public: virtual void print_status(const String& status, CharCount cursor_pos = -1) = 0; + void insert(Editor& editor, IncrementalInserter::Mode mode); + void repeat_last_insert(Editor& editor, Context& context); + void prompt(const String& prompt, Completer completer, PromptCallback callback); @@ -45,14 +49,15 @@ public: void on_next_key(KeyCallback callback); void handle_next_input(Context& context); - virtual Key get_key() = 0; private: virtual void show_menu(const memoryview& choices) = 0; virtual void menu_ctrl(MenuCommand command) = 0; - + virtual Key get_key() = 0; void reset_normal_mode(); + std::pair> m_last_insert; + class Mode { public: @@ -71,6 +76,7 @@ private: class MenuMode; class PromptMode; class NextKeyMode; + class InsertMode; }; struct prompt_aborted {}; diff --git a/src/main.cc b/src/main.cc index 1030c4fa..aa4a828f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -32,91 +32,15 @@ namespace Kakoune bool quit_requested = false; -struct InsertSequence -{ - IncrementalInserter::Mode mode; - std::vector keys; - - InsertSequence() : mode(IncrementalInserter::Mode::Insert) {} -}; - -InsertSequence last_insert_sequence; - -template -void insert_sequence(IncrementalInserter& inserter, - const Context& context, - GetKey get_key, Redraw redraw) -{ - while (true) - { - Key key = get_key(); - switch (key.modifiers) - { - case Key::Modifiers::None: - switch (key.key) - { - case 27: - return; - default: - inserter.insert(String() + key.key); - } - break; - case Key::Modifiers::Control: - switch (key.key) - { - case 'r': - { - Key next_key = get_key(); - if (next_key.modifiers == Key::Modifiers::None) - inserter.insert(RegisterManager::instance()[next_key.key].values(context)); - break; - } - case 'm': - inserter.insert(String() + '\n'); - break; - case 'i': - inserter.insert(String() + '\t'); - break; - case 'd': - inserter.move_cursors({0, -1}); - break; - case 'e': - inserter.move_cursors({0, 1}); - break; - case 'g': - inserter.erase(); - break; - } - break; - } - redraw(); - } -} - template void do_insert(Context& context) { - last_insert_sequence.mode = mode; - last_insert_sequence.keys.clear(); - IncrementalInserter inserter(context.editor(), mode); - context.draw_ifn(); - insert_sequence(inserter, context, - [&]() { Key key = context.client().get_key(); - last_insert_sequence.keys.push_back(key); - return key; }, - [&]() { context.draw_ifn(); }); + context.client().insert(context.editor(), mode); } void do_repeat_insert(Context& context) { - if (last_insert_sequence.keys.empty()) - return; - - IncrementalInserter inserter(context.editor(), last_insert_sequence.mode); - size_t index = 0; - insert_sequence(inserter, context, - [&]() { return last_insert_sequence.keys[index++]; }, - [](){}); + context.client().repeat_last_insert(context.editor(), context); } template