Handle inserting in Client::InsertMode

This commit is contained in:
Maxime Coste 2012-09-05 14:27:14 +02:00
parent d4446d1525
commit bf42d77469
3 changed files with 92 additions and 82 deletions

View File

@ -309,9 +309,89 @@ private:
KeyCallback m_callback; KeyCallback m_callback;
}; };
Client::Client() class Client::InsertMode : public Client::Mode
: m_mode(new NormalMode(*this))
{ {
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<Key> 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<NormalMode*>(m_mode.get()) != nullptr);
} }
void Client::prompt(const String& prompt, Completer completer, void Client::prompt(const String& prompt, Completer completer,

View File

@ -5,6 +5,7 @@
#include "completion.hh" #include "completion.hh"
#include "utils.hh" #include "utils.hh"
#include "string.hh" #include "string.hh"
#include "editor.hh"
namespace Kakoune namespace Kakoune
{ {
@ -36,6 +37,9 @@ public:
virtual void print_status(const String& status, virtual void print_status(const String& status,
CharCount cursor_pos = -1) = 0; 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, void prompt(const String& prompt, Completer completer,
PromptCallback callback); PromptCallback callback);
@ -45,14 +49,15 @@ public:
void on_next_key(KeyCallback callback); void on_next_key(KeyCallback callback);
void handle_next_input(Context& context); void handle_next_input(Context& context);
virtual Key get_key() = 0;
private: private:
virtual void show_menu(const memoryview<String>& choices) = 0; virtual void show_menu(const memoryview<String>& choices) = 0;
virtual void menu_ctrl(MenuCommand command) = 0; virtual void menu_ctrl(MenuCommand command) = 0;
virtual Key get_key() = 0;
void reset_normal_mode(); void reset_normal_mode();
std::pair<IncrementalInserter::Mode, std::vector<Key>> m_last_insert;
class Mode class Mode
{ {
public: public:
@ -71,6 +76,7 @@ private:
class MenuMode; class MenuMode;
class PromptMode; class PromptMode;
class NextKeyMode; class NextKeyMode;
class InsertMode;
}; };
struct prompt_aborted {}; struct prompt_aborted {};

View File

@ -32,91 +32,15 @@ namespace Kakoune
bool quit_requested = false; bool quit_requested = false;
struct InsertSequence
{
IncrementalInserter::Mode mode;
std::vector<Key> keys;
InsertSequence() : mode(IncrementalInserter::Mode::Insert) {}
};
InsertSequence last_insert_sequence;
template<typename GetKey, typename Redraw>
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<IncrementalInserter::Mode mode> template<IncrementalInserter::Mode mode>
void do_insert(Context& context) void do_insert(Context& context)
{ {
last_insert_sequence.mode = mode; context.client().insert(context.editor(), 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(); });
} }
void do_repeat_insert(Context& context) void do_repeat_insert(Context& context)
{ {
if (last_insert_sequence.keys.empty()) context.client().repeat_last_insert(context.editor(), context);
return;
IncrementalInserter inserter(context.editor(), last_insert_sequence.mode);
size_t index = 0;
insert_sequence(inserter, context,
[&]() { return last_insert_sequence.keys[index++]; },
[](){});
} }
template<bool append> template<bool append>