From b43fdc7eb67f282ff37b98ceb19077185228885b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 18 Feb 2013 18:58:07 +0100 Subject: [PATCH] Add macro recording/replay support --- src/input_handler.cc | 26 ++++++++++++++++++++++++++ src/input_handler.hh | 7 +++++++ src/keys.cc | 3 ++- src/main.cc | 30 ++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/input_handler.cc b/src/input_handler.cc index 68d8f576..88f986ba 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -690,9 +690,35 @@ void InputHandler::handle_available_inputs() { Key key = m_context.ui().get_key(); if (is_valid(key)) + { + const bool was_recording = is_recording(); + m_mode->on_key(key); + + // do not record the key that made us enter or leave recording mode. + if (was_recording and is_recording()) + m_recorded_keys += key_to_str(key); + } m_mode_trash.clear(); } } +void InputHandler::start_recording(char reg) +{ + assert(m_recording_reg == 0); + m_recording_reg = reg; +} + +bool InputHandler::is_recording() const +{ + return m_recording_reg != 0; +} + +void InputHandler::stop_recording() +{ + assert(m_recording_reg != 0); + RegisterManager::instance()[m_recording_reg] = memoryview(m_recorded_keys); + m_recording_reg = 0; +} + } diff --git a/src/input_handler.hh b/src/input_handler.hh index 9089273d..ad93ef9f 100644 --- a/src/input_handler.hh +++ b/src/input_handler.hh @@ -65,6 +65,10 @@ public: // user interface void handle_available_inputs(); + void start_recording(char reg); + bool is_recording() const; + void stop_recording(); + Context& context() { return m_context; } private: Context m_context; @@ -74,6 +78,9 @@ private: using Insertion = std::pair>; Insertion m_last_insert = {InsertMode::Insert, {}}; + + char m_recording_reg = 0; + String m_recorded_keys; }; struct prompt_aborted {}; diff --git a/src/keys.cc b/src/keys.cc index d9c304d6..70853351 100644 --- a/src/keys.cc +++ b/src/keys.cc @@ -23,7 +23,8 @@ static std::vector keynamemap = { { "left", Key::Left }, { "right", Key::Right }, { "up", Key::Up }, - { "down", Key::Down} + { "down", Key::Down}, + { "backspace", Key::Backspace} }; KeyList parse_keys(const String& str) diff --git a/src/main.cc b/src/main.cc index 15e31317..118ab4c7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -405,6 +405,33 @@ void select_to_next_char(Context& context) }); } +void start_or_end_macro_recording(Context& context) +{ + if (context.input_handler().is_recording()) + context.input_handler().stop_recording(); + else + context.input_handler().on_next_key([](const Key& key, Context& context) { + if (key.modifiers == Key::Modifiers::None) + context.input_handler().start_recording(key.key); + }); +} + +void replay_macro(Context& context) +{ + int count = context.numeric_param(); + context.input_handler().on_next_key([count](const Key& key, Context& context) mutable { + if (key.modifiers == Key::Modifiers::None) + { + memoryview reg_val = RegisterManager::instance()[key.key].values(context); + if (not reg_val.empty()) + { + scoped_edition edition(context.editor()); + do { exec_keys(parse_keys(reg_val[0]), context); } while (--count > 0); + } + } + }); +} + enum class JumpDirection { Forward, Backward }; template void jump(Context& context) @@ -590,6 +617,9 @@ std::unordered_map> keymap = { { Key::Modifiers::Control, 'o' }, jump }, { { Key::Modifiers::Alt, 'r' }, do_rotate_selections }, + + { { Key::Modifiers::None, 'q' }, start_or_end_macro_recording }, + { { Key::Modifiers::None, '@' }, replay_macro }, }; }