summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-02-18 18:58:07 +0100
committerMaxime Coste <frrrwww@gmail.com>2013-02-18 18:58:07 +0100
commitb43fdc7eb67f282ff37b98ceb19077185228885b (patch)
tree2013b00556d639e752022562d7aeee0beb28c00d /src
parent577734dae725739aa1fe6f87334253441385f24a (diff)
Add macro recording/replay support
Diffstat (limited to 'src')
-rw-r--r--src/input_handler.cc26
-rw-r--r--src/input_handler.hh7
-rw-r--r--src/keys.cc3
-rw-r--r--src/main.cc30
4 files changed, 65 insertions, 1 deletions
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<String>(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<InsertMode, std::vector<Key>>;
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<KeyAndName> 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<String> 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<JumpDirection direction>
void jump(Context& context)
@@ -590,6 +617,9 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
{ { Key::Modifiers::Control, 'o' }, jump<JumpDirection::Backward> },
{ { Key::Modifiers::Alt, 'r' }, do_rotate_selections },
+
+ { { Key::Modifiers::None, 'q' }, start_or_end_macro_recording },
+ { { Key::Modifiers::None, '@' }, replay_macro },
};
}