diff --git a/src/main.cc b/src/main.cc index f21dcde6..418ead97 100644 --- a/src/main.cc +++ b/src/main.cc @@ -311,7 +311,7 @@ void do_deindent(Context& context) editor.erase(); } -template +template void do_select_object(Context& context) { context.input_handler().on_next_key( @@ -319,18 +319,18 @@ void do_select_object(Context& context) typedef std::function Selector; static const std::unordered_map key_to_selector = { - { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) }, - { { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) }, - { { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, inner) }, - { { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) }, - { { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) }, - { { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, inner) }, - { { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, inner) }, - { { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, inner) }, - { { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, inner) }, - { { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, inner) }, - { { Key::Modifiers::None, 'w' }, std::bind(select_whole_word, _1, inner) }, - { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, inner) }, + { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, CodepointPair{ '(', ')' }, flags) }, + { { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, CodepointPair{ '{', '}' }, flags) }, + { { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) }, + { { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, CodepointPair{ '[', ']' }, flags) }, + { { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) }, + { { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, CodepointPair{ '<', '>' }, flags) }, + { { Key::Modifiers::None, 'w' }, std::bind(select_whole_word, _1, flags & SurroundFlags::Inner) }, + { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, flags & SurroundFlags::Inner) }, }; auto it = key_to_selector.find(key); @@ -535,8 +535,10 @@ std::unordered_map> 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().redo()) { context.print_status("nothing left to redo"); } }) }, - { { Key::Modifiers::Alt, 'i' }, do_select_object }, - { { Key::Modifiers::Alt, 'a' }, do_select_object }, + { { Key::Modifiers::Alt, 'i' }, do_select_object }, + { { Key::Modifiers::Alt, 'a' }, do_select_object }, + { { Key::Modifiers::None, ']' }, do_select_object }, + { { Key::Modifiers::None, '[' }, do_select_object }, { { Key::Modifiers::Alt, 'w' }, repeated([](Context& context) { context.editor().select(select_to_next_word); }) }, { { Key::Modifiers::Alt, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end); }) }, diff --git a/src/selectors.cc b/src/selectors.cc index d900cf9f..c1023594 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -224,51 +224,61 @@ Selection select_matching(const Selection& selection) Selection select_surrounding(const Selection& selection, 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(); - while (not is_begin(first)) + if (to_begin) { - if (first != selection.last() and *first == matching.second) - ++level; - else if (*first == matching.first) + int level = 0; + while (not is_begin(first)) { - if (level == 0) - break; - else - --level; + if (first != selection.last() and *first == matching.second) + ++level; + else if (*first == matching.first) + { + if (level == 0) + break; + else + --level; + } + --first; } - --first; + if (level != 0 or *first != matching.first) + return selection; } - if (level != 0 or *first != matching.first) - return selection; - level = 0; - Utf8Iterator last = first + 1; - while (not is_end(last)) + Utf8Iterator last = selection.last(); + if (to_end) { - if (*last == matching.first) - ++level; - else if (*last == matching.second) + int level = 0; + last = first + 1; + while (not is_end(last)) { - if (level == 0) - break; - else - --level; + if (*last == matching.first) + ++level; + else if (*last == matching.second) + { + if (level == 0) + break; + else + --level; + } + ++last; } - ++last; + if (level != 0 or *last != matching.second) + return selection; } - if (level != 0 or *last != matching.second) - return selection; - if (inside) + if (flags & SurroundFlags::Inner) { - ++first; - if (first != last) + if (to_begin) + ++first; + if (to_end and first != last) --last; } - return utf8_selection(first, last); + return to_end ? utf8_selection(first, last) : utf8_selection(last, first); } Selection select_to(const Selection& selection, diff --git a/src/selectors.hh b/src/selectors.hh index 806c27ac..2026cb4d 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -2,7 +2,7 @@ #define selectors_hh_INCLUDED #include "selection.hh" -#include "utf8.hh" +#include "unicode.hh" namespace Kakoune { @@ -17,10 +17,6 @@ Selection select_to_previous_word(const Selection& selection); Selection select_line(const Selection& selection); Selection select_matching(const Selection& selection); -using CodepointPair = std::pair; -Selection select_surrounding(const Selection& selection, - const CodepointPair& matching, bool inside); - Selection select_to(const Selection& selection, Codepoint c, int count, bool inclusive); Selection select_to_reverse(const Selection& selection, @@ -43,6 +39,22 @@ SelectionList select_all_matches(const Selection& selection, SelectionList split_selection(const Selection& selection, 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; +Selection select_surrounding(const Selection& selection, + const CodepointPair& matching, + SurroundFlags flags); + } #endif // selectors_hh_INCLUDED