summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-01-07 18:53:27 +0100
committerMaxime Coste <frrrwww@gmail.com>2013-01-07 18:53:27 +0100
commit3f7bf82cdeb68bd3e73dcff4545bf23045fcfb73 (patch)
tree564d68ed7a0d169f0e48ef18ea74ae9af75bdc62
parent4fc598cd48af95b66bf3b3351b39b5a348ccc58d (diff)
Support for selecting to surrounding object begin/end with [ and ]
-rw-r--r--src/main.cc32
-rw-r--r--src/selectors.cc70
-rw-r--r--src/selectors.hh22
3 files changed, 74 insertions, 50 deletions
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<bool inner>
+template<SurroundFlags flags>
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<Selection (const Selection&)> 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{ '(', ')' }, 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<false>, _1, inner) },
- { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _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<false>, _1, flags & SurroundFlags::Inner) },
+ { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word<true>, _1, flags & SurroundFlags::Inner) },
};
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().redo()) { context.print_status("nothing left to redo"); } }) },
- { { Key::Modifiers::Alt, 'i' }, do_select_object<true> },
- { { Key::Modifiers::Alt, 'a' }, do_select_object<false> },
+ { { Key::Modifiers::Alt, 'i' }, do_select_object<SurroundFlags::ToBegin | SurroundFlags::ToEnd | SurroundFlags::Inner> },
+ { { 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, 'e' }, repeated([](Context& context) { context.editor().select(select_to_next_word_end<true>); }) },
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<Codepoint, Codepoint>;
-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<Codepoint, Codepoint>;
+Selection select_surrounding(const Selection& selection,
+ const CodepointPair& matching,
+ SurroundFlags flags);
+
}
#endif // selectors_hh_INCLUDED