summaryrefslogtreecommitdiff
path: root/src/normal.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2018-03-01 15:21:55 +1100
committerMaxime Coste <mawww@kakoune.org>2018-03-01 15:21:55 +1100
commitf907e6cc46c4b3e63a6d984c0bd51b4e1e67e456 (patch)
treee541c5e6933549467093abec539108a20744f8b1 /src/normal.cc
parent34c7db0ea724b16a32ca72601448b7eb29bf9112 (diff)
Reintroduce complex selection merging behaviour
Selection merging is necessary if we want X to work nicely when we are on EOL (jumping to next line is as nice as it could be, and we are much more often on EOL nowadays).
Diffstat (limited to 'src/normal.cc')
-rw-r--r--src/normal.cc32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/normal.cc b/src/normal.cc
index 171132ba..176f8c0c 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -20,6 +20,7 @@
#include "shell_manager.hh"
#include "string.hh"
#include "user_interface.hh"
+#include "unit_tests.hh"
#include "window.hh"
namespace Kakoune
@@ -34,6 +35,33 @@ enum class SelectMode
Append,
};
+void merge_selections(Selection& sel, const Selection& new_sel)
+{
+ const bool forward = sel.cursor() >= sel.anchor();
+ const bool new_forward = new_sel.cursor() > new_sel.anchor();
+ if (forward and new_forward)
+ sel.anchor() = std::min(sel.anchor(), new_sel.anchor());
+ const bool backward = sel.cursor() <= sel.anchor();
+ const bool new_backward = new_sel.cursor() < new_sel.anchor();
+ if (backward and new_backward)
+ sel.anchor() = std::max(sel.anchor(), new_sel.anchor());
+
+ sel.cursor() = new_sel.cursor();
+}
+
+UnitTest test_merge_selection{[] {
+ auto merge = [](Selection sel, const Selection& new_sel) {
+ merge_selections(sel, new_sel);
+ return sel;
+ };
+ kak_assert(merge({{0, 1}, {0, 2} }, {{0, 3}, {0, 4}}) == Selection{{0, 1}, {0, 4}});
+ kak_assert(merge({{0, 1}, {0, 2} }, {{0, 1}, {0, 2}}) == Selection{{0, 1}, {0, 2}});
+ kak_assert(merge({{0, 1}, {0, 2} }, {{0, 0}, {0, 0}}) == Selection{{0, 1}, {0, 0}});
+ kak_assert(merge({{0, 1}, {0, 2} }, {{0, 0}, {0, 3}}) == Selection{{0, 0}, {0, 3}});
+ kak_assert(merge({{0, 1}, {0, 3} }, {{0, 4}, {0, 2}}) == Selection{{0, 1}, {0, 2}});
+ kak_assert(merge({{0, 1}, {0, 2} }, {{0, 1}, {0, 1}}) == Selection{{0, 1}, {0, 1}});
+}};
+
template<SelectMode mode, typename T>
void select(Context& context, T func)
{
@@ -63,7 +91,7 @@ void select(Context& context, T func)
}
if (mode == SelectMode::Extend)
- sel.cursor() = res->cursor();
+ merge_selections(sel, *res);
else
{
sel.anchor() = res->anchor();
@@ -788,7 +816,7 @@ void search(Context& context, NormalParams params)
if (mode == SelectMode::Replace)
sel = keep_direction(find_next_match<direction>(context, sel, regex, wrapped), sel);
if (mode == SelectMode::Extend)
- sel.cursor() = find_next_match<direction>(context, sel, regex, wrapped).cursor();
+ merge_selections(sel, find_next_match<direction>(context, sel, regex, wrapped));
}
selections.sort_and_merge_overlapping();
} while (--c > 0);