diff --git a/src/normal.cc b/src/normal.cc index c0370015..c7b074a4 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -973,8 +973,10 @@ void select_regex(Context& context, NormalParams params) RegisterManager::instance()[reg].set(context, ex.str()); + auto& selections = context.selections(); + auto& buffer = selections.buffer(); if (not ex.empty() and not ex.str().empty()) - select_all_matches(context.selections(), ex, capture); + selections = SelectionList{buffer, select_matches(buffer, selections, ex, capture)}; }); } @@ -998,8 +1000,10 @@ void split_regex(Context& context, NormalParams params) RegisterManager::instance()[reg].set(context, ex.str()); + auto& selections = context.selections(); + auto& buffer = selections.buffer(); if (not ex.empty() and not ex.str().empty()) - split_selections(context.selections(), ex, capture); + selections = SelectionList{buffer, split_on_matches(buffer, selections, ex, capture)}; }); } diff --git a/src/selection.hh b/src/selection.hh index c08bca9c..02266528 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -129,6 +129,7 @@ struct SelectionList void remove(size_t index); + const Selection* data() const { return m_selections.data(); } size_t size() const { return m_selections.size(); } bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; } diff --git a/src/selectors.cc b/src/selectors.cc index e33dc21e..c6bb1901 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -3,11 +3,10 @@ #include "buffer_utils.hh" #include "context.hh" #include "flags.hh" -#include "optional.hh" #include "option_types.hh" #include "regex.hh" +#include "selection.hh" #include "string.hh" -#include "unicode.hh" #include "unit_tests.hh" #include "utf8_iterator.hh" @@ -38,6 +37,13 @@ ConstArrayView get_extra_word_chars(const Context& context) } +Selection keep_direction(Selection res, const Selection& ref) +{ + if ((res.cursor() < res.anchor()) != (ref.cursor() < ref.anchor())) + std::swap(res.cursor(), res.anchor()); + return res; +} + template Optional select_to_next_word(const Context& context, const Selection& selection) @@ -913,14 +919,13 @@ Selection find_next_match(const Context& context, const Selection& sel, const Re template Selection find_next_match(const Context&, const Selection&, const Regex&, bool&); template Selection find_next_match(const Context&, const Selection&, const Regex&, bool&); -void select_all_matches(SelectionList& selections, const Regex& regex, int capture) +Vector select_matches(const Buffer& buffer, ConstArrayView selections, const Regex& regex, int capture) { const int mark_count = (int)regex.mark_count(); if (capture < 0 or capture > mark_count) throw runtime_error("invalid capture number"); Vector result; - auto& buffer = selections.buffer(); ThreadedRegexVM vm{*regex.impl()}; for (auto& sel : selections) { @@ -948,26 +953,22 @@ void select_all_matches(SelectionList& selections, const Regex& regex, int captu } if (result.empty()) throw runtime_error("nothing selected"); - - // Avoid SelectionList::operator=(Vector) as we know result is - // already sorted and non overlapping. - selections = SelectionList{buffer, std::move(result)}; + return result; } -void split_selections(SelectionList& selections, const Regex& regex, int capture) +Vector split_on_matches(const Buffer& buffer, ConstArrayView selections, const Regex& regex, int capture) { if (capture < 0 or capture > (int)regex.mark_count()) throw runtime_error("invalid capture number"); Vector result; - auto& buffer = selections.buffer(); auto buf_end = buffer.end(); auto buf_begin = buffer.begin(); ThreadedRegexVM vm{*regex.impl()}; for (auto& sel : selections) { auto begin = buffer.iterator_at(sel.min()); - auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end()); + auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buf_end); for (auto&& match : RegexIterator{begin, sel_end, vm, match_flags(buffer, begin, sel_end)}) { @@ -987,8 +988,7 @@ void split_selections(SelectionList& selections, const Regex& regex, int capture } if (result.empty()) throw runtime_error("nothing selected"); - - selections = std::move(result); + return result; } UnitTest test_find_surrounding{[]() diff --git a/src/selectors.hh b/src/selectors.hh index 2f0b4dc7..a82e29a2 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -1,20 +1,20 @@ #ifndef selectors_hh_INCLUDED #define selectors_hh_INCLUDED -#include "selection.hh" +#include "optional.hh" +#include "meta.hh" +#include "unicode.hh" +#include "vector.hh" namespace Kakoune { +class Selection; +class Buffer; class Regex; class Context; -inline Selection keep_direction(Selection res, const Selection& ref) -{ - if ((res.cursor() < res.anchor()) != (ref.cursor() < ref.anchor())) - std::swap(res.cursor(), res.anchor()); - return res; -} +Selection keep_direction(Selection res, const Selection& ref); template Optional @@ -103,8 +103,13 @@ template Selection find_next_match(const Context& context, const Selection& sel, const Regex& regex, bool& wrapped); -void select_all_matches(SelectionList& selections, const Regex& regex, int capture = 0); -void split_selections(SelectionList& selections, const Regex& regex, int capture = 0); +Vector +select_matches(const Buffer& buffer, ConstArrayView selections, + const Regex& regex, int capture = 0); + +Vector +split_on_matches(const Buffer& buffer, ConstArrayView selections, + const Regex& regex, int capture = 0); Optional select_surrounding(const Context& context, const Selection& selection,