Add support for repeating the last object/char find command
This is a potential solution for #794.
This commit is contained in:
parent
f6cdc2eee5
commit
8b6eba8208
|
@ -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;
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user