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).
This commit is contained in:
Maxime Coste 2018-03-01 15:21:55 +11:00
parent 34c7db0ea7
commit f907e6cc46

View File

@ -20,6 +20,7 @@
#include "shell_manager.hh" #include "shell_manager.hh"
#include "string.hh" #include "string.hh"
#include "user_interface.hh" #include "user_interface.hh"
#include "unit_tests.hh"
#include "window.hh" #include "window.hh"
namespace Kakoune namespace Kakoune
@ -34,6 +35,33 @@ enum class SelectMode
Append, 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> template<SelectMode mode, typename T>
void select(Context& context, T func) void select(Context& context, T func)
{ {
@ -63,7 +91,7 @@ void select(Context& context, T func)
} }
if (mode == SelectMode::Extend) if (mode == SelectMode::Extend)
sel.cursor() = res->cursor(); merge_selections(sel, *res);
else else
{ {
sel.anchor() = res->anchor(); sel.anchor() = res->anchor();
@ -788,7 +816,7 @@ void search(Context& context, NormalParams params)
if (mode == SelectMode::Replace) if (mode == SelectMode::Replace)
sel = keep_direction(find_next_match<direction>(context, sel, regex, wrapped), sel); sel = keep_direction(find_next_match<direction>(context, sel, regex, wrapped), sel);
if (mode == SelectMode::Extend) 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(); selections.sort_and_merge_overlapping();
} while (--c > 0); } while (--c > 0);