DynamicSelectionList: derive from SelectionList
the previous implementation did not preserve invariant either, so we'd better use less code.
This commit is contained in:
parent
57ad454b53
commit
1c94064713
|
@ -5,9 +5,10 @@ namespace Kakoune
|
||||||
|
|
||||||
DynamicSelectionList::DynamicSelectionList(const Buffer& buffer,
|
DynamicSelectionList::DynamicSelectionList(const Buffer& buffer,
|
||||||
SelectionList selections)
|
SelectionList selections)
|
||||||
: m_buffer(&buffer), m_selections(std::move(selections))
|
: m_buffer(&buffer), SelectionList(std::move(selections))
|
||||||
{
|
{
|
||||||
m_buffer->add_change_listener(*this);
|
m_buffer->add_change_listener(*this);
|
||||||
|
check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSelectionList::~DynamicSelectionList()
|
DynamicSelectionList::~DynamicSelectionList()
|
||||||
|
@ -16,51 +17,59 @@ DynamicSelectionList::~DynamicSelectionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSelectionList::DynamicSelectionList(const DynamicSelectionList& other)
|
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);
|
m_buffer->add_change_listener(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other)
|
DynamicSelectionList& DynamicSelectionList::operator=(const DynamicSelectionList& other)
|
||||||
{
|
{
|
||||||
m_selections = other.m_selections;
|
SelectionList::operator=((const SelectionList&)other);
|
||||||
if (m_buffer != other.m_buffer)
|
if (m_buffer != other.m_buffer)
|
||||||
{
|
{
|
||||||
m_buffer->remove_change_listener(*this);
|
m_buffer->remove_change_listener(*this);
|
||||||
m_buffer = other.m_buffer;
|
m_buffer = other.m_buffer;
|
||||||
m_buffer->add_change_listener(*this);
|
m_buffer->add_change_listener(*this);
|
||||||
}
|
}
|
||||||
|
check_invariant();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSelectionList::DynamicSelectionList(DynamicSelectionList&& other)
|
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);
|
m_buffer->add_change_listener(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other)
|
DynamicSelectionList& DynamicSelectionList::operator=(DynamicSelectionList&& other)
|
||||||
{
|
{
|
||||||
m_selections = std::move(other.m_selections);
|
SelectionList::operator=(std::move(other));
|
||||||
if (m_buffer != other.m_buffer)
|
if (m_buffer != other.m_buffer)
|
||||||
{
|
{
|
||||||
m_buffer->remove_change_listener(*this);
|
m_buffer->remove_change_listener(*this);
|
||||||
m_buffer = other.m_buffer;
|
m_buffer = other.m_buffer;
|
||||||
m_buffer->add_change_listener(*this);
|
m_buffer->add_change_listener(*this);
|
||||||
}
|
}
|
||||||
|
check_invariant();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicSelectionList::reset(SelectionList selections)
|
DynamicSelectionList& DynamicSelectionList::operator=(SelectionList selections)
|
||||||
{
|
{
|
||||||
for (auto& sel : selections)
|
SelectionList::operator=(std::move(selections));
|
||||||
assert(&sel.buffer() == m_buffer);
|
check_invariant();
|
||||||
m_selections = std::move(selections);
|
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)
|
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.first().on_insert(begin.coord(), end.coord());
|
||||||
sel.last().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)
|
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.first().on_erase(begin.coord(), end.coord());
|
||||||
sel.last().on_erase(begin.coord(), end.coord());
|
sel.last().on_erase(begin.coord(), end.coord());
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
class DynamicSelectionList : public BufferChangeListener
|
class DynamicSelectionList : public SelectionList, public BufferChangeListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = SelectionList::iterator;
|
using iterator = SelectionList::iterator;
|
||||||
|
@ -20,34 +20,8 @@ public:
|
||||||
DynamicSelectionList(DynamicSelectionList&& other);
|
DynamicSelectionList(DynamicSelectionList&& other);
|
||||||
DynamicSelectionList& operator=(DynamicSelectionList&& other);
|
DynamicSelectionList& operator=(DynamicSelectionList&& other);
|
||||||
|
|
||||||
size_t size() const { return m_selections.size(); }
|
DynamicSelectionList& operator=(SelectionList selections);
|
||||||
bool empty() const { return m_selections.empty(); }
|
void check_invariant() const;
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
const Buffer& buffer() const { return *m_buffer; }
|
const Buffer& buffer() const { return *m_buffer; }
|
||||||
|
|
||||||
|
@ -58,7 +32,6 @@ private:
|
||||||
const BufferIterator& end) override;
|
const BufferIterator& end) override;
|
||||||
|
|
||||||
const Buffer* m_buffer;
|
const Buffer* m_buffer;
|
||||||
SelectionList m_selections;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -102,7 +102,7 @@ void Editor::insert(const memoryview<String>& strings, InsertMode mode)
|
||||||
|
|
||||||
for (size_t i = 0; i < selections().size(); ++i)
|
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);
|
BufferIterator pos = prepare_insert(*m_buffer, sel, mode);
|
||||||
size_t index = std::min(i, strings.size()-1);
|
size_t index = std::min(i, strings.size()-1);
|
||||||
m_buffer->insert(pos, strings[index]);
|
m_buffer->insert(pos, strings[index]);
|
||||||
|
@ -119,7 +119,7 @@ std::vector<String> Editor::selections_content() const
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void merge_overlapping(DynamicSelectionList& selections)
|
static void merge_overlapping(SelectionList& selections)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < selections.size(); ++i)
|
for (size_t i = 0; i < selections.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -174,8 +174,7 @@ void Editor::clear_selections()
|
||||||
pos = utf8::previous(pos);
|
pos = utf8::previous(pos);
|
||||||
|
|
||||||
Selection sel = Selection(pos, pos);
|
Selection sel = Selection(pos, pos);
|
||||||
m_selections.clear();
|
m_selections = SelectionList{ std::move(sel) };
|
||||||
m_selections.push_back(std::move(sel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::flip_selections()
|
void Editor::flip_selections()
|
||||||
|
@ -190,11 +189,7 @@ void Editor::keep_selection(int index)
|
||||||
check_invariant();
|
check_invariant();
|
||||||
|
|
||||||
if (index < m_selections.size())
|
if (index < m_selections.size())
|
||||||
{
|
m_selections = SelectionList{ std::move(m_selections[index]) };
|
||||||
Selection sel = std::move(m_selections[index]);
|
|
||||||
m_selections.clear();
|
|
||||||
m_selections.push_back(std::move(sel));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::remove_selection(int index)
|
void Editor::remove_selection(int index)
|
||||||
|
@ -207,15 +202,14 @@ void Editor::remove_selection(int index)
|
||||||
|
|
||||||
void Editor::select(const BufferIterator& iterator)
|
void Editor::select(const BufferIterator& iterator)
|
||||||
{
|
{
|
||||||
m_selections.clear();
|
m_selections = SelectionList{ {iterator, iterator} };
|
||||||
m_selections.push_back(Selection(iterator, iterator));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::select(SelectionList selections)
|
void Editor::select(SelectionList selections)
|
||||||
{
|
{
|
||||||
if (selections.empty())
|
if (selections.empty())
|
||||||
throw runtime_error("no selections");
|
throw runtime_error("no selections");
|
||||||
m_selections.reset(std::move(selections));
|
m_selections = std::move(selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::select(const Selector& selector, SelectMode mode)
|
void Editor::select(const Selector& selector, SelectMode mode)
|
||||||
|
@ -272,9 +266,8 @@ void Editor::multi_select(const MultiSelector& selector)
|
||||||
}
|
}
|
||||||
if (new_selections.empty())
|
if (new_selections.empty())
|
||||||
throw nothing_selected();
|
throw nothing_selected();
|
||||||
|
merge_overlapping(new_selections);
|
||||||
m_selections.reset(std::move(new_selections));
|
m_selections = std::move(new_selections);
|
||||||
merge_overlapping(m_selections);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LastModifiedRangeListener : public BufferChangeListener
|
class LastModifiedRangeListener : public BufferChangeListener
|
||||||
|
@ -315,10 +308,7 @@ bool Editor::undo()
|
||||||
LastModifiedRangeListener listener(buffer());
|
LastModifiedRangeListener listener(buffer());
|
||||||
bool res = m_buffer->undo();
|
bool res = m_buffer->undo();
|
||||||
if (res)
|
if (res)
|
||||||
{
|
m_selections = SelectionList{ {listener.first(), listener.last()} };
|
||||||
m_selections.clear();
|
|
||||||
m_selections.push_back({listener.first(), listener.last()});
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,16 +317,14 @@ bool Editor::redo()
|
||||||
LastModifiedRangeListener listener(buffer());
|
LastModifiedRangeListener listener(buffer());
|
||||||
bool res = m_buffer->redo();
|
bool res = m_buffer->redo();
|
||||||
if (res)
|
if (res)
|
||||||
{
|
m_selections = SelectionList{ {listener.first(), listener.last()} };
|
||||||
m_selections.clear();
|
|
||||||
m_selections.push_back({listener.first(), listener.last()});
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::check_invariant() const
|
void Editor::check_invariant() const
|
||||||
{
|
{
|
||||||
assert(not m_selections.empty());
|
assert(not m_selections.empty());
|
||||||
|
m_selections.check_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::begin_edition()
|
void Editor::begin_edition()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user