From 1b30c0f4fbc9bad48d0689fd748206ce7072b38d Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 1 Jun 2014 15:57:12 +0100 Subject: [PATCH] Extract merge_overlapping as a free function template --- src/normal.cc | 22 +++++++++------------- src/selection.cc | 4 ++-- src/selection.hh | 48 ++++++++++++++++++++++++------------------------ 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/normal.cc b/src/normal.cc index cc7eaa88..92e5727a 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1155,7 +1155,7 @@ void spaces_to_tabs(Context& context, int ts) } } -static boost::optional compute_modified_ranges(Buffer& buffer, size_t timestamp) +static std::vector compute_modified_ranges(Buffer& buffer, size_t timestamp) { std::vector ranges; for (auto& change : buffer.changes_since(timestamp)) @@ -1183,29 +1183,25 @@ static boost::optional compute_modified_ranges(Buffer& buffer, si ranges.insert(it, Selection{pos, pos}); } } - if (ranges.empty()) - return {}; - for (auto& sel : ranges) { sel.anchor() = buffer.clamp(sel.anchor()); sel.cursor() = buffer.clamp(sel.cursor()); } - SelectionList result{buffer, std::move(ranges)}; - auto touches = [&](const Selection& lhs, const Selection& rhs) { return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min() : lhs.min() <= buffer.char_next(rhs.max()); }; - result.merge_overlapping(touches); + size_t main = 0; + merge_overlapping(ranges.begin(), ranges.end(), main, touches); - for (auto& sel : result) + for (auto& sel : ranges) { if (sel.anchor() != sel.cursor()) sel.cursor() = buffer.char_prev(sel.cursor()); } - return result; + return ranges; } void undo(Context& context, int) @@ -1216,8 +1212,8 @@ void undo(Context& context, int) if (res) { auto ranges = compute_modified_ranges(buffer, timestamp); - if (ranges) - context.selections() = std::move(*ranges); + if (not ranges.empty()) + context.selections() = std::move(ranges); } else if (not res) context.print_status({ "nothing left to undo", get_color("Information") }); @@ -1232,8 +1228,8 @@ void redo(Context& context, int) if (res) { auto ranges = compute_modified_ranges(buffer, timestamp); - if (ranges) - context.selections() = std::move(*ranges); + if (not ranges.empty()) + context.selections() = std::move(ranges); } else if (not res) diff --git a/src/selection.cc b/src/selection.cc index b45c1898..c96baa37 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -166,7 +166,7 @@ void SelectionList::update() sel.anchor() = m_buffer->clamp(sel.anchor()); sel.cursor() = m_buffer->clamp(sel.cursor()); } - merge_overlapping(overlaps); + m_selections.erase(merge_overlapping(begin(), end(), m_main, overlaps), end()); check_invariant(); m_timestamp = m_buffer->timestamp(); @@ -208,7 +208,7 @@ void SelectionList::sort_and_merge_overlapping() return begin < main_begin; }); std::stable_sort(begin(), end(), compare_selections); - merge_overlapping(overlaps); + m_selections.erase(merge_overlapping(begin(), end(), m_main, overlaps), end()); } namespace { diff --git a/src/selection.hh b/src/selection.hh index 652a558f..d9c2ea87 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -71,6 +71,30 @@ enum class InsertMode : unsigned OpenLineAbove }; +template +Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsFunc overlaps) +{ + kak_assert(std::is_sorted(begin, end, compare_selections)); + size_t size = end - begin; + size_t i = 0; + for (size_t j = 1; j < size; ++j) + { + if (overlaps(begin[i], begin[j])) + { + begin[i].merge_with(begin[j]); + if (i < main) + --main; + } + else + { + ++i; + if (i != j) + begin[i] = std::move(begin[j]); + } + } + return begin + i + 1; +} + struct SelectionList { SelectionList(Buffer& buffer, Selection s); @@ -122,30 +146,6 @@ struct SelectionList bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; } bool operator!=(const SelectionList& other) const { return !((*this) == other); } - template - void merge_overlapping(OverlapsFunc overlaps) - { - kak_assert(std::is_sorted(begin(), end(), compare_selections)); - size_t i = 0; - for (size_t j = 1; j < size(); ++j) - { - if (overlaps((*this)[i], (*this)[j])) - { - (*this)[i].merge_with((*this)[j]); - if (i < m_main) - --m_main; - } - else - { - ++i; - if (i != j) - (*this)[i] = std::move((*this)[j]); - } - } - m_selections.erase(begin() + i + 1, end()); - kak_assert(std::is_sorted(begin(), end(), compare_selections)); - } - void sort_and_merge_overlapping(); Buffer& buffer() const { return *m_buffer; }