From e74b581b0a7c6a196d0d6efa1d92e309e48483d1 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 12 Jan 2018 07:51:19 +1100 Subject: [PATCH] Save/restore main selection from/to strings Always consider that the first selection in the list is the main one, save selections that way. This approach was suggested by PR #1786 but the implementation here is different, and is used more generally whenever we save selections to strings. This is also the prefered way to work only on the main selection: save selections with Z, reduce to main with , restore with z. Closes #1786 Fixes #1750 --- src/normal.cc | 9 ++++----- src/ranges.hh | 4 ++-- src/selection.cc | 40 +++++++++++++++++++++++----------------- src/selection.hh | 4 ++++ 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/normal.cc b/src/normal.cc index dea938eb..fe129216 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1620,14 +1620,13 @@ SelectionList read_selections_from_register(char reg, Context& context) Buffer& buffer = BufferManager::instance().get_buffer({arobase+1, percent}); size_t timestamp = str_to_int({percent + 1, desc.end()}); - Vector sels; - for (auto sel_desc : StringView{desc.begin(), arobase} | split(':')) - sels.push_back(selection_from_string(sel_desc)); - + auto sels = StringView{desc.begin(), arobase} | split(':') + | transform(selection_from_string) + | gather>(); if (sels.empty()) throw runtime_error(format("Register {} contains an empty selection list", reg)); - return {buffer, std::move(sels), timestamp}; + return {SelectionList::UnsortedTag{}, buffer, std::move(sels), timestamp}; } enum class CombineOp diff --git a/src/ranges.hh b/src/ranges.hh index aebe6f50..df622ea5 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -249,8 +249,8 @@ auto split(Element separator, Element escaper) template struct ConcatView { - using RangeIt1 = decltype(begin(std::declval())); - using RangeIt2 = decltype(begin(std::declval())); + using RangeIt1 = decltype(std::declval().begin()); + using RangeIt2 = decltype(std::declval().begin()); using ValueType = typename std::common_type_t::value_type, typename std::iterator_traits::value_type>; diff --git a/src/selection.cc b/src/selection.cc index 87c8eade..5f323894 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -16,16 +16,26 @@ SelectionList::SelectionList(Buffer& buffer, Selection s, size_t timestamp) SelectionList::SelectionList(Buffer& buffer, Selection s) : SelectionList(buffer, std::move(s), buffer.timestamp()) {} -SelectionList::SelectionList(Buffer& buffer, Vector s, size_t timestamp) - : m_buffer(&buffer), m_selections(std::move(s)), m_timestamp(timestamp) +SelectionList::SelectionList(Buffer& buffer, Vector list, size_t timestamp) + : m_buffer(&buffer), m_selections(std::move(list)), m_timestamp(timestamp) { kak_assert(size() > 0); m_main = size() - 1; check_invariant(); } -SelectionList::SelectionList(Buffer& buffer, Vector s) - : SelectionList(buffer, std::move(s), buffer.timestamp()) {} +SelectionList::SelectionList(Buffer& buffer, Vector list) + : SelectionList(buffer, std::move(list), buffer.timestamp()) {} + +SelectionList::SelectionList(SelectionList::UnsortedTag, Buffer& buffer, Vector list) + : SelectionList(UnsortedTag{}, buffer, std::move(list), buffer.timestamp()) {} + +SelectionList::SelectionList(SelectionList::UnsortedTag, Buffer& buffer, Vector list, size_t timestamp) + : m_buffer(&buffer), m_selections(std::move(list)), m_timestamp(timestamp) +{ + sort_and_merge_overlapping(); + check_invariant(); +} void SelectionList::remove(size_t index) { @@ -480,7 +490,11 @@ String selection_to_string(const Selection& selection) String selection_list_to_string(const SelectionList& selections) { - return join(selections | transform(selection_to_string), ':', false); + auto beg = &*selections.begin(), end = &*selections.end(); + auto main = beg + selections.main_index(); + using View = ConstArrayView; + return join(concatenated(View{main, end}, View{beg, main}) | + transform(selection_to_string), ':', false); } Selection selection_from_string(StringView desc) @@ -510,18 +524,10 @@ SelectionList selection_list_from_string(Buffer& buffer, StringView desc) if (desc.empty()) throw runtime_error{"empty selection description"}; - Vector sels; - for (auto sel_desc : desc | split(':')) - { - auto sel = selection_from_string(sel_desc); - clamp(sel, buffer); - sels.push_back(sel); - } - size_t main = 0; - std::sort(sels.begin(), sels.end(), compare_selections); - sels.erase(merge_overlapping(sels.begin(), sels.end(), main, overlaps), sels.end()); - - return {buffer, std::move(sels)}; + auto sels = desc | split(':') + | transform([&](auto&& d) { auto s = selection_from_string(d); clamp(s, buffer); return s; }) + | gather>(); + return {SelectionList::UnsortedTag{}, buffer, std::move(sels)}; } } diff --git a/src/selection.hh b/src/selection.hh index 1f492b43..864b02d8 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -87,6 +87,10 @@ struct SelectionList SelectionList(Buffer& buffer, Vector s); SelectionList(Buffer& buffer, Vector s, size_t timestamp); + struct UnsortedTag {}; + SelectionList(UnsortedTag, Buffer& buffer, Vector s); + SelectionList(UnsortedTag, Buffer& buffer, Vector s, size_t timestamp); + void update(); void check_invariant() const;