Use the "<reg> syntax along with a default register for marks and macros

Marks use the '^' register by default, macros the '@' register.
This commit is contained in:
Maxime Coste 2015-08-19 13:58:37 +01:00
parent baf0203b9d
commit 7ee027b125

View File

@ -1049,17 +1049,17 @@ static bool is_basic_alpha(Codepoint c)
return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z'); return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
} }
void start_or_end_macro_recording(Context& context, NormalParams) void start_or_end_macro_recording(Context& context, NormalParams params)
{ {
if (context.input_handler().is_recording()) if (context.input_handler().is_recording())
context.input_handler().stop_recording(); context.input_handler().stop_recording();
else else
on_next_key_with_autoinfo(context, KeymapMode::None, {
[](Key key, Context& context) { const char reg = tolower(params.reg ? params.reg : '@');
auto cp = key.codepoint(); if (not is_basic_alpha(reg) and reg != '@')
if (cp and is_basic_alpha(*cp)) throw runtime_error("Macros can only use the '@' and alphabetic registers");
context.input_handler().start_recording(tolower(*cp)); context.input_handler().start_recording(reg);
}, "record macro", "enter macro name "); }
} }
void end_macro_recording(Context& context, NormalParams) void end_macro_recording(Context& context, NormalParams)
@ -1070,29 +1070,25 @@ void end_macro_recording(Context& context, NormalParams)
void replay_macro(Context& context, NormalParams params) void replay_macro(Context& context, NormalParams params)
{ {
on_next_key_with_autoinfo(context, KeymapMode::None, const char reg = tolower(params.reg ? params.reg : '@');
[params](Key key, Context& context) mutable { if (not is_basic_alpha(reg) and reg != '@')
auto cp = key.codepoint(); throw runtime_error("Macros can only use the '@' and alphabetic registers");
if (cp and is_basic_alpha(*cp))
{
static bool running_macros[26] = {};
const char name = tolower(*cp);
const size_t idx = (size_t)(name - 'a');
if (running_macros[idx])
throw runtime_error("recursive macros call detected");
ConstArrayView<String> reg_val = RegisterManager::instance()[name].values(context); static bool running_macros[27] = {};
if (not reg_val.empty()) const size_t idx = reg != '@' ? (size_t)(reg - 'a') : 26;
{ if (running_macros[idx])
running_macros[idx] = true; throw runtime_error("recursive macros call detected");
auto stop = on_scope_end([&]{ running_macros[idx] = false; });
auto keys = parse_keys(reg_val[0]); ConstArrayView<String> reg_val = RegisterManager::instance()[reg].values(context);
ScopedEdition edition(context); if (not reg_val.empty())
do { exec_keys(keys, context); } while (--params.count > 0); {
} running_macros[idx] = true;
} auto stop = on_scope_end([&]{ running_macros[idx] = false; });
}, "replay macro", "enter macro name");
auto keys = parse_keys(reg_val[0]);
ScopedEdition edition(context);
do { exec_keys(keys, context); } while (--params.count > 0);
}
} }
template<Direction direction> template<Direction direction>
@ -1264,61 +1260,55 @@ void spaces_to_tabs(Context& context, NormalParams params)
SelectionList{ buffer, std::move(spaces) }.insert("\t"_str, InsertMode::Replace); SelectionList{ buffer, std::move(spaces) }.insert("\t"_str, InsertMode::Replace);
} }
void save_selections(Context& context, NormalParams) void save_selections(Context& context, NormalParams params)
{ {
on_next_key_with_autoinfo(context, KeymapMode::None, const char reg = tolower(params.reg ? params.reg : '^');
[](Key key, Context& context) { if (not is_basic_alpha(reg) and reg != '^')
auto cp = key.codepoint(); throw runtime_error("selections can only be saved to the '^' and alphabetic registers");
if (not cp or not is_basic_alpha(*cp))
return;
String desc = format("{}@{}%{}", String desc = format("{}@{}%{}",
selection_list_to_string(context.selections()), selection_list_to_string(context.selections()),
context.buffer().name(), context.buffer().name(),
context.buffer().timestamp()); context.buffer().timestamp());
RegisterManager::instance()[*cp] = desc; RegisterManager::instance()[reg] = desc;
context.print_status({format("Saved selections in register '{}'", *cp), get_face("Information")}); context.print_status({format("Saved selections in register '{}'", reg), get_face("Information")});
}, "Save selections", "Enter register to save selections into");
} }
void restore_selections(Context& context, NormalParams) void restore_selections(Context& context, NormalParams params)
{ {
on_next_key_with_autoinfo(context, KeymapMode::None, const char reg = tolower(params.reg ? params.reg : '^');
[](Key key, Context& context) { if (not is_basic_alpha(reg) and reg != '^')
auto cp = key.codepoint(); throw runtime_error("selections can only be saved to the '^' and alphabetic registers");
if (not cp or not is_basic_alpha(*cp))
return;
auto content = RegisterManager::instance()[*cp].values(context); auto content = RegisterManager::instance()[reg].values(context);
if (content.size() != 1) if (content.size() != 1)
throw runtime_error(format("Register {} does not contain a selections desc", *cp)); throw runtime_error(format("Register {} does not contain a selections desc", reg));
StringView desc = content[0]; StringView desc = content[0];
auto arobase = find(desc, '@'); auto arobase = find(desc, '@');
auto percent = find(desc, '%'); auto percent = find(desc, '%');
if (arobase == desc.end() or percent == desc.end()) if (arobase == desc.end() or percent == desc.end())
throw runtime_error(format("Register {} does not contain a selections desc", *cp)); throw runtime_error(format("Register {} does not contain a selections desc", reg));
Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent}); Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent});
size_t timestamp = str_to_int({percent + 1, desc.end()}); size_t timestamp = str_to_int({percent + 1, desc.end()});
Vector<Selection> sels; Vector<Selection> sels;
for (auto sel_desc : split({desc.begin(), arobase}, ':')) for (auto sel_desc : split({desc.begin(), arobase}, ':'))
sels.push_back(selection_from_string(sel_desc)); sels.push_back(selection_from_string(sel_desc));
SelectionList sel_list{buffer, std::move(sels), timestamp}; SelectionList sel_list{buffer, std::move(sels), timestamp};
if (&buffer != &context.buffer()) if (&buffer != &context.buffer())
context.change_buffer(buffer); context.change_buffer(buffer);
context.selections_write_only() = std::move(sel_list); context.selections_write_only() = std::move(sel_list);
context.print_status({format("Restored selections from register '{}'", *cp), get_face("Information")}); context.print_status({format("Restored selections from register '{}'", reg), get_face("Information")});
}, "Restore selections", "Enter register to restore selections from");
} }
void undo(Context& context, NormalParams) void undo(Context& context, NormalParams)