From 1c940647133d98d2ae43581b0d5e0671b97e0618 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 12 Dec 2012 14:21:50 +0100 Subject: [PATCH] DynamicSelectionList: derive from SelectionList the previous implementation did not preserve invariant either, so we'd better use less code. --- src/dynamic_selection_list.cc | 31 ++++++++++++++++++++----------- src/dynamic_selection_list.hh | 33 +++------------------------------ src/editor.cc | 34 +++++++++++----------------------- 3 files changed, 34 insertions(+), 64 deletions(-) diff --git a/src/dynamic_selection_list.cc b/src/dynamic_selection_list.cc index e1a78168..05b90501 100644 --- a/src/dynamic_selection_list.cc +++ b/src/dynamic_selection_list.cc @@ -5,9 +5,10 @@ namespace Kakoune DynamicSelectionList::DynamicSelectionList(const Buffer& buffer, SelectionList selections) - : m_buffer(&buffer), m_selections(std::move(selections)) + : m_buffer(&buffer), SelectionList(std::move(selections)) { m_buffer->add_change_listener(*this); + check_invariant(); } DynamicSelectionList::~DynamicSelectionList() @@ -16,51 +17,59 @@ DynamicSelectionList::~DynamicSelectionList() } DynamicSelectionList::DynamicSelectionList(const DynamicSelectionList& other) - : m_selections(other.m_selections), m_buffer(other.m_buffer) + : SelectionList(other), m_buffer(other.m_buffer) { m_buffer->add_change_listener(*this); } DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other) { - m_selections = other.m_selections; + SelectionList::operator=((const SelectionList&)other); if (m_buffer != other.m_buffer) { m_buffer->remove_change_listener(*this); m_buffer = other.m_buffer; m_buffer->add_change_listener(*this); } + check_invariant(); return *this; } DynamicSelectionList::DynamicSelectionList(DynamicSelectionList&& other) - : m_selections(std::move(other.m_selections)), m_buffer(other.m_buffer) + : SelectionList(std::move(other)), m_buffer(other.m_buffer) { m_buffer->add_change_listener(*this); } DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other) { - m_selections = std::move(other.m_selections); + SelectionList::operator=(std::move(other)); if (m_buffer != other.m_buffer) { m_buffer->remove_change_listener(*this); m_buffer = other.m_buffer; m_buffer->add_change_listener(*this); } + check_invariant(); return *this; } -void DynamicSelectionList::reset(SelectionList selections) +DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections) { - for (auto& sel : selections) - assert(&sel.buffer() == m_buffer); - m_selections = std::move(selections); + SelectionList::operator=(std::move(selections)); + check_invariant(); + return *this; +} + +void DynamicSelectionList::check_invariant() const +{ + for (auto& sel : *this) + assert(m_buffer == &sel.buffer()); } void DynamicSelectionList::on_insert(const BufferIterator& begin, const BufferIterator& end) { - for (auto& sel : m_selections) + for (auto& sel : *this) { sel.first().on_insert(begin.coord(), end.coord()); sel.last().on_insert(begin.coord(), end.coord()); @@ -70,7 +79,7 @@ void DynamicSelectionList::on_insert(const BufferIterator& begin, const BufferIt void DynamicSelectionList::on_erase(const BufferIterator& begin, const BufferIterator& end) { - for (auto& sel : m_selections) + for (auto& sel : *this) { sel.first().on_erase(begin.coord(), end.coord()); sel.last().on_erase(begin.coord(), end.coord()); diff --git a/src/dynamic_selection_list.hh b/src/dynamic_selection_list.hh index 5e76f662..4ae34969 100644 --- a/src/dynamic_selection_list.hh +++ b/src/dynamic_selection_list.hh @@ -6,7 +6,7 @@ namespace Kakoune { -class DynamicSelectionList : public BufferChangeListener +class DynamicSelectionList : public SelectionList, public BufferChangeListener { public: using iterator = SelectionList::iterator; @@ -20,34 +20,8 @@ public: DynamicSelectionList(DynamicSelectionList&& other); DynamicSelectionList& operator=(DynamicSelectionList&& other); - size_t size() const { return m_selections.size(); } - bool empty() const { return m_selections.empty(); } - - void clear() { m_selections.clear(); } - iterator erase(iterator it) { return m_selections.erase(it); } - - void push_back(Selection selection) - { - assert(&selection.buffer() == m_buffer); - m_selections.push_back(std::move(selection)); - } - - void reset(SelectionList selections); - - iterator begin() { return m_selections.begin(); } - iterator end() { return m_selections.end(); } - const_iterator begin() const { return m_selections.begin(); } - const_iterator end() const { return m_selections.end(); } - - Selection& front() { return m_selections.front(); } - Selection& back() { return m_selections.back(); } - const Selection& front() const { return m_selections.front(); } - const Selection& back() const { return m_selections.back(); } - - Selection& operator[](size_t index) { return m_selections[index]; } - const Selection& operator[](size_t index) const { return m_selections[index]; } - - operator const SelectionList&() const { return m_selections; } + DynamicSelectionList& operator=(SelectionList selections); + void check_invariant() const; const Buffer& buffer() const { return *m_buffer; } @@ -58,7 +32,6 @@ private: const BufferIterator& end) override; const Buffer* m_buffer; - SelectionList m_selections; }; }; diff --git a/src/editor.cc b/src/editor.cc index 554dd327..d41ffe5f 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -102,7 +102,7 @@ void Editor::insert(const memoryview& strings, InsertMode mode) for (size_t i = 0; i < selections().size(); ++i) { - Selection& sel = m_selections[i]; + auto& sel = m_selections[i]; BufferIterator pos = prepare_insert(*m_buffer, sel, mode); size_t index = std::min(i, strings.size()-1); m_buffer->insert(pos, strings[index]); @@ -119,7 +119,7 @@ std::vector Editor::selections_content() const return contents; } -static void merge_overlapping(DynamicSelectionList& selections) +static void merge_overlapping(SelectionList& selections) { for (size_t i = 0; i < selections.size(); ++i) { @@ -174,8 +174,7 @@ void Editor::clear_selections() pos = utf8::previous(pos); Selection sel = Selection(pos, pos); - m_selections.clear(); - m_selections.push_back(std::move(sel)); + m_selections = SelectionList{ std::move(sel) }; } void Editor::flip_selections() @@ -190,11 +189,7 @@ void Editor::keep_selection(int index) check_invariant(); if (index < m_selections.size()) - { - Selection sel = std::move(m_selections[index]); - m_selections.clear(); - m_selections.push_back(std::move(sel)); - } + m_selections = SelectionList{ std::move(m_selections[index]) }; } void Editor::remove_selection(int index) @@ -207,15 +202,14 @@ void Editor::remove_selection(int index) void Editor::select(const BufferIterator& iterator) { - m_selections.clear(); - m_selections.push_back(Selection(iterator, iterator)); + m_selections = SelectionList{ {iterator, iterator} }; } void Editor::select(SelectionList selections) { if (selections.empty()) throw runtime_error("no selections"); - m_selections.reset(std::move(selections)); + m_selections = std::move(selections); } void Editor::select(const Selector& selector, SelectMode mode) @@ -272,9 +266,8 @@ void Editor::multi_select(const MultiSelector& selector) } if (new_selections.empty()) throw nothing_selected(); - - m_selections.reset(std::move(new_selections)); - merge_overlapping(m_selections); + merge_overlapping(new_selections); + m_selections = std::move(new_selections); } class LastModifiedRangeListener : public BufferChangeListener @@ -315,10 +308,7 @@ bool Editor::undo() LastModifiedRangeListener listener(buffer()); bool res = m_buffer->undo(); if (res) - { - m_selections.clear(); - m_selections.push_back({listener.first(), listener.last()}); - } + m_selections = SelectionList{ {listener.first(), listener.last()} }; return res; } @@ -327,16 +317,14 @@ bool Editor::redo() LastModifiedRangeListener listener(buffer()); bool res = m_buffer->redo(); if (res) - { - m_selections.clear(); - m_selections.push_back({listener.first(), listener.last()}); - } + m_selections = SelectionList{ {listener.first(), listener.last()} }; return res; } void Editor::check_invariant() const { assert(not m_selections.empty()); + m_selections.check_invariant(); } void Editor::begin_edition()