Support for selecting to surrounding object begin/end with [ and ]
This commit is contained in:
parent
4fc598cd48
commit
3f7bf82cde
32
src/main.cc
32
src/main.cc
|
@ -311,7 +311,7 @@ void do_deindent(Context& context)
|
||||||
editor.erase();
|
editor.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool inner>
|
template<SurroundFlags flags>
|
||||||
void do_select_object(Context& context)
|
void do_select_object(Context& context)
|
||||||
{
|
{
|
||||||
context.input_handler().on_next_key(
|
context.input_handler().on_next_key(
|
||||||
|
@ -319,18 +319,18 @@ void do_select_object(Context& context)
|
||||||
typedef std::function<Selection (const Selection&)> Selector;
|
typedef std::function<Selection (const Selection&)> Selector;
|
||||||
static const std::unordered_map<Key, Selector> key_to_selector =
|
static const std::unordered_map<Key, Selector> key_to_selector =
|
||||||
{
|
{
|
||||||
{ { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) },
|
{ { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) },
|
||||||
{ { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) },
|
{ { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) },
|
||||||
{ { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) },
|
{ { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) },
|
||||||
{ { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) },
|
{ { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) },
|
||||||
{ { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) },
|
{ { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) },
|
||||||
{ { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) },
|
{ { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) },
|
||||||
{ { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, inner) },
|
{ { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) },
|
||||||
{ { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, inner) },
|
{ { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) },
|
||||||
{ { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, inner) },
|
{ { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) },
|
||||||
{ { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, inner) },
|
{ { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) },
|
||||||
{ { Key::Modifiers::None, 'w' }, std::bind(select_whole_word<false>, _1, inner) },
|
{ { Key::Modifiers::None, 'w' }, std::bind(select_whole_word<false>, _1, flags & SurroundFlags::Inner) },
|
||||||
{ { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _1, inner) },
|
{ { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _1, flags & SurroundFlags::Inner) },
|
||||||
};
|
};
|
||||||
|
|
||||||
auto it = key_to_selector.find(key);
|
auto it = key_to_selector.find(key);
|
||||||
|
@ -535,8 +535,10 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
|
||||||
{ { Key::Modifiers::None, 'u' }, repeated([](Context& context) { if (not context.editor().undo()) { context.print_status("nothing left to undo"); } }) },
|
{ { Key::Modifiers::None, 'u' }, repeated([](Context& context) { if (not context.editor().undo()) { context.print_status("nothing left to undo"); } }) },
|
||||||
{ { Key::Modifiers::None, 'U' }, repeated([](Context& context) { if (not context.editor().redo()) { context.print_status("nothing left to redo"); } }) },
|
{ { Key::Modifiers::None, 'U' }, repeated([](Context& context) { if (not context.editor().redo()) { context.print_status("nothing left to redo"); } }) },
|
||||||
|
|
||||||
{ { Key::Modifiers::Alt, 'i' }, do_select_object<true> },
|
{ { Key::Modifiers::Alt, 'i' }, do_select_object<SurroundFlags::ToBegin | SurroundFlags::ToEnd | SurroundFlags::Inner> },
|
||||||
{ { Key::Modifiers::Alt, 'a' }, do_select_object<false> },
|
{ { Key::Modifiers::Alt, 'a' }, do_select_object<SurroundFlags::ToBegin | SurroundFlags::ToEnd> },
|
||||||
|
{ { Key::Modifiers::None, ']' }, do_select_object<SurroundFlags::ToEnd> },
|
||||||
|
{ { Key::Modifiers::None, '[' }, do_select_object<SurroundFlags::ToBegin> },
|
||||||
|
|
||||||
{ { Key::Modifiers::Alt, 'w' }, repeated([](Context& context) { context.editor().select(select_to_next_word<true>); }) },
|
{ { Key::Modifiers::Alt, 'w' }, repeated([](Context& context) { context.editor().select(select_to_next_word<true>); }) },
|
||||||
{ { Key::Modifiers::Alt, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) },
|
{ { Key::Modifiers::Alt, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) },
|
||||||
|
|
|
@ -224,10 +224,14 @@ Selection select_matching(const Selection& selection)
|
||||||
|
|
||||||
Selection select_surrounding(const Selection& selection,
|
Selection select_surrounding(const Selection& selection,
|
||||||
const CodepointPair& matching,
|
const CodepointPair& matching,
|
||||||
bool inside)
|
SurroundFlags flags)
|
||||||
{
|
{
|
||||||
int level = 0;
|
const bool to_begin = flags & SurroundFlags::ToBegin;
|
||||||
|
const bool to_end = flags & SurroundFlags::ToEnd;
|
||||||
Utf8Iterator first = selection.last();
|
Utf8Iterator first = selection.last();
|
||||||
|
if (to_begin)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
while (not is_begin(first))
|
while (not is_begin(first))
|
||||||
{
|
{
|
||||||
if (first != selection.last() and *first == matching.second)
|
if (first != selection.last() and *first == matching.second)
|
||||||
|
@ -243,9 +247,13 @@ Selection select_surrounding(const Selection& selection,
|
||||||
}
|
}
|
||||||
if (level != 0 or *first != matching.first)
|
if (level != 0 or *first != matching.first)
|
||||||
return selection;
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
level = 0;
|
Utf8Iterator last = selection.last();
|
||||||
Utf8Iterator last = first + 1;
|
if (to_end)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
last = first + 1;
|
||||||
while (not is_end(last))
|
while (not is_end(last))
|
||||||
{
|
{
|
||||||
if (*last == matching.first)
|
if (*last == matching.first)
|
||||||
|
@ -261,14 +269,16 @@ Selection select_surrounding(const Selection& selection,
|
||||||
}
|
}
|
||||||
if (level != 0 or *last != matching.second)
|
if (level != 0 or *last != matching.second)
|
||||||
return selection;
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
if (inside)
|
if (flags & SurroundFlags::Inner)
|
||||||
{
|
{
|
||||||
|
if (to_begin)
|
||||||
++first;
|
++first;
|
||||||
if (first != last)
|
if (to_end and first != last)
|
||||||
--last;
|
--last;
|
||||||
}
|
}
|
||||||
return utf8_selection(first, last);
|
return to_end ? utf8_selection(first, last) : utf8_selection(last, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection select_to(const Selection& selection,
|
Selection select_to(const Selection& selection,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define selectors_hh_INCLUDED
|
#define selectors_hh_INCLUDED
|
||||||
|
|
||||||
#include "selection.hh"
|
#include "selection.hh"
|
||||||
#include "utf8.hh"
|
#include "unicode.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -17,10 +17,6 @@ Selection select_to_previous_word(const Selection& selection);
|
||||||
Selection select_line(const Selection& selection);
|
Selection select_line(const Selection& selection);
|
||||||
Selection select_matching(const Selection& selection);
|
Selection select_matching(const Selection& selection);
|
||||||
|
|
||||||
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
|
||||||
Selection select_surrounding(const Selection& selection,
|
|
||||||
const CodepointPair& matching, bool inside);
|
|
||||||
|
|
||||||
Selection select_to(const Selection& selection,
|
Selection select_to(const Selection& selection,
|
||||||
Codepoint c, int count, bool inclusive);
|
Codepoint c, int count, bool inclusive);
|
||||||
Selection select_to_reverse(const Selection& selection,
|
Selection select_to_reverse(const Selection& selection,
|
||||||
|
@ -43,6 +39,22 @@ SelectionList select_all_matches(const Selection& selection,
|
||||||
SelectionList split_selection(const Selection& selection,
|
SelectionList split_selection(const Selection& selection,
|
||||||
const String& separator_regex);
|
const String& separator_regex);
|
||||||
|
|
||||||
|
enum class SurroundFlags
|
||||||
|
{
|
||||||
|
ToBegin = 1,
|
||||||
|
ToEnd = 2,
|
||||||
|
Inner = 4
|
||||||
|
};
|
||||||
|
constexpr bool operator&(SurroundFlags lhs, SurroundFlags rhs)
|
||||||
|
{ return (bool)((int)lhs & (int) rhs); }
|
||||||
|
constexpr SurroundFlags operator|(SurroundFlags lhs, SurroundFlags rhs)
|
||||||
|
{ return (SurroundFlags)((int)lhs | (int) rhs); }
|
||||||
|
|
||||||
|
using CodepointPair = std::pair<Codepoint, Codepoint>;
|
||||||
|
Selection select_surrounding(const Selection& selection,
|
||||||
|
const CodepointPair& matching,
|
||||||
|
SurroundFlags flags);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // selectors_hh_INCLUDED
|
#endif // selectors_hh_INCLUDED
|
||||||
|
|
Loading…
Reference in New Issue
Block a user