Add support for repeating the last object/char find command

This is a potential solution for #794.
This commit is contained in:
Maxime Coste 2016-10-11 00:20:36 +01:00
parent f6cdc2eee5
commit 8b6eba8208
2 changed files with 53 additions and 25 deletions

View File

@ -70,6 +70,8 @@ private:
size_t m_current = 0; size_t m_current = 0;
}; };
using LastSelectFunc = std::function<void (Context&)>;
// A Context is used to access non singleton objects for various services // A Context is used to access non singleton objects for various services
// in commands. // in commands.
// //
@ -150,6 +152,11 @@ public:
JumpList& jump_list() { return m_jump_list; } JumpList& jump_list() { return m_jump_list; }
void push_jump() { m_jump_list.push(selections()); } void push_jump() { m_jump_list.push(selections()); }
template<typename Func>
void set_last_select(Func&& last_select) { m_last_select = std::forward<Func>(last_select); }
void repeat_last_select() { if (m_last_select) m_last_select(*this); }
private: private:
void begin_edition(); void begin_edition();
void end_edition(); void end_edition();
@ -169,6 +176,8 @@ private:
JumpList m_jump_list; JumpList m_jump_list;
LastSelectFunc m_last_select;
NestedBool m_hooks_disabled; NestedBool m_hooks_disabled;
NestedBool m_keymaps_disabled; NestedBool m_keymaps_disabled;
NestedBool m_history_disabled; NestedBool m_history_disabled;

View File

@ -70,6 +70,14 @@ void select(Context& context, NormalParams)
select<mode>(context, func); select<mode>(context, func);
} }
template<SelectMode mode, typename Func>
void select_and_set_last(Context& context, Func&& func)
{
context.set_last_select(
[func](Context& context){ select<mode>(context, func); });
return select<mode>(context, func);
}
template<SelectMode mode = SelectMode::Replace> template<SelectMode mode = SelectMode::Replace>
void select_coord(Buffer& buffer, BufferCoord coord, SelectionList& selections) void select_coord(Buffer& buffer, BufferCoord coord, SelectionList& selections)
{ {
@ -95,6 +103,11 @@ void repeat_last_insert(Context& context, NormalParams)
context.input_handler().repeat_last_insert(); context.input_handler().repeat_last_insert();
} }
void repeat_last_select(Context& context, NormalParams)
{
context.repeat_last_select();
}
template<SelectMode mode> template<SelectMode mode>
void goto_commands(Context& context, NormalParams params) void goto_commands(Context& context, NormalParams params)
{ {
@ -944,7 +957,7 @@ void select_object(Context& context, NormalParams params)
if (cp == -1) if (cp == -1)
return; return;
static constexpr struct static constexpr struct ObjectType
{ {
Codepoint key; Codepoint key;
Selection (*func)(const Buffer&, const Selection&, int, ObjectFlags); Selection (*func)(const Buffer&, const Selection&, int, ObjectFlags);
@ -958,11 +971,10 @@ void select_object(Context& context, NormalParams params)
{ 'n', select_number }, { 'n', select_number },
{ 'u', select_argument }, { 'u', select_argument },
}; };
for (auto& sel : selectors) auto obj_it = find(selectors | transform(std::mem_fn(&ObjectType::key)), cp).base();
{ if (obj_it != std::end(selectors))
if (cp == sel.key) return select_and_set_last<mode>(
return select<mode>(context, std::bind(sel.func, _1, _2, count, flags)); context, std::bind(obj_it->func, _1, _2, count, flags));
}
if (cp == ':') if (cp == ':')
{ {
@ -983,13 +995,15 @@ void select_object(Context& context, NormalParams params)
if (params.size() != 2) if (params.size() != 2)
throw runtime_error{"desc parsing failed, expected <open>,<close>"}; throw runtime_error{"desc parsing failed, expected <open>,<close>"};
return select<mode>(context, std::bind(select_surrounding, _1, _2, select_and_set_last<mode>(
params[0], params[1], count, flags)); context, std::bind(select_surrounding, _1, _2,
params[0], params[1],
count, flags));
}); });
return; return;
} }
static constexpr struct static constexpr struct SurroundingPair
{ {
StringView opening; StringView opening;
StringView closing; StringView closing;
@ -1003,22 +1017,24 @@ void select_object(Context& context, NormalParams params)
{ "'", "'", 'q' }, { "'", "'", 'q' },
{ "`", "`", 'g' }, { "`", "`", 'g' },
}; };
for (auto& sur : surrounding_pairs) auto pair_it = find_if(surrounding_pairs,
{ [cp](const SurroundingPair& s) {
if (sur.opening[0_char] == cp or return s.opening[0_char] == cp or
sur.closing[0_char] == cp or s.closing[0_char] == cp or
(sur.name != 0 and sur.name == cp)) (s.name != 0 and s.name == cp);
return select<mode>(context, std::bind(select_surrounding, _1, _2, });
sur.opening, sur.closing, if (pair_it != std::end(surrounding_pairs))
count, flags)); return select_and_set_last<mode>(
} context, std::bind(select_surrounding, _1, _2,
pair_it->opening, pair_it->closing,
count, flags));
if (is_punctuation(cp)) if (is_punctuation(cp))
{ {
auto utf8cp = to_string(cp); auto utf8cp = to_string(cp);
return select<mode>(context, std::bind(select_surrounding, _1, _2, return select_and_set_last<mode>(
utf8cp, utf8cp, context, std::bind(select_surrounding, _1, _2,
count, flags)); utf8cp, utf8cp, count, flags));
} }
}, get_title(), }, get_title(),
"b,(,): parenthesis block\n" "b,(,): parenthesis block\n"
@ -1133,10 +1149,12 @@ void select_to_next_char(Context& context, NormalParams params)
constexpr auto new_flags = flags & SelectFlags::Extend ? SelectMode::Extend constexpr auto new_flags = flags & SelectFlags::Extend ? SelectMode::Extend
: SelectMode::Replace; : SelectMode::Replace;
if (auto cp = key.codepoint()) if (auto cp = key.codepoint())
select<new_flags>( select_and_set_last<new_flags>(
context, context,
std::bind(flags & SelectFlags::Reverse ? select_to_reverse : select_to, std::bind(flags & SelectFlags::Reverse ? select_to_reverse
_1, _2, *cp, params.count, flags & SelectFlags::Inclusive)); : select_to,
_1, _2, *cp, params.count,
flags & SelectFlags::Inclusive));
}, get_title(),"enter char to select to"); }, get_title(),"enter char to select to");
} }
@ -1658,6 +1676,7 @@ static NormalCmdDesc cmds[] =
{ alt('s'), "split selected text on line ends", split_lines }, { alt('s'), "split selected text on line ends", split_lines },
{ '.', "repeat last insert command", repeat_last_insert }, { '.', "repeat last insert command", repeat_last_insert },
{ alt('.'), "repeat last object select/character find", repeat_last_select },
{ '%', "select whole buffer", select_whole_buffer }, { '%', "select whole buffer", select_whole_buffer },