Add macro recording/replay support

This commit is contained in:
Maxime Coste 2013-02-18 18:58:07 +01:00
parent 577734dae7
commit b43fdc7eb6
4 changed files with 65 additions and 1 deletions

View File

@ -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;
}
}

View File

@ -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 {};

View File

@ -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)

View File

@ -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 },
};
}