summaryrefslogtreecommitdiff
path: root/src/editor.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-05-02 19:31:58 +0200
committerMaxime Coste <frrrwww@gmail.com>2013-05-03 18:44:26 +0200
commit564cfb084e6098625c64de6a75fb7441d71287f6 (patch)
tree2b13975b8b855bac640bb44c8ee6a4d20797802c /src/editor.cc
parent4c4b6a404dff8c3e22d4ddfe52b3bf21f946e098 (diff)
Editor: undo and redo select all ranges modified instead of the last one
Diffstat (limited to 'src/editor.cc')
-rw-r--r--src/editor.cc88
1 files changed, 49 insertions, 39 deletions
diff --git a/src/editor.cc b/src/editor.cc
index e7fc1412..aa7fd1d5 100644
--- a/src/editor.cc
+++ b/src/editor.cc
@@ -128,22 +128,30 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
return lhs.begin() < rhs.begin();
}
-static void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection)
+template<bool already_sorted = false>
+void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection)
{
if (selections.size() == 1)
return;
- const auto& main = selections[main_selection];
- const auto main_begin = main.begin();
- main_selection = std::count_if(selections.begin(), selections.end(),
- [&](const Selection& sel) {
- auto begin = sel.begin();
- if (begin == main_begin)
- return &sel < &main;
- else
- return sel.begin() < main_begin;
- });
- std::stable_sort(selections.begin(), selections.end(), compare_selections);
+ if (already_sorted)
+ {
+ kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
+ }
+ else
+ {
+ const auto& main = selections[main_selection];
+ const auto main_begin = main.begin();
+ main_selection = std::count_if(selections.begin(), selections.end(),
+ [&](const Selection& sel) {
+ auto begin = sel.begin();
+ if (begin == main_begin)
+ return &sel < &main;
+ else
+ return sel.begin() < main_begin;
+ });
+ std::stable_sort(selections.begin(), selections.end(), compare_selections);
+ }
for (size_t i = 0; i+1 < selections.size() and selections.size() > 1;)
{
@@ -339,50 +347,51 @@ void Editor::multi_select(const MultiSelector& selector)
check_invariant();
}
-class LastModifiedRangeListener : public BufferChangeListener
+class ModifiedRangesListener : public BufferChangeListener_AutoRegister
{
public:
- LastModifiedRangeListener(Buffer& buffer)
- : m_buffer(buffer)
- { m_buffer.change_listeners().insert(this); }
-
- ~LastModifiedRangeListener()
- { m_buffer.change_listeners().erase(this); }
+ ModifiedRangesListener(Buffer& buffer)
+ : BufferChangeListener_AutoRegister(buffer) {}
void on_insert(const BufferIterator& begin, const BufferIterator& end)
{
kak_assert(begin.is_valid());
kak_assert(end.is_valid());
- m_first = begin;
- m_last = utf8::previous(end);
+ m_ranges.update_insert(begin.coord(), end.coord());
+ auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin,
+ [](const BufferIterator& it, const Selection& sel)
+ { return it < sel.begin(); });
+ m_ranges.emplace(it, begin, utf8::previous(end));
}
void on_erase(const BufferIterator& begin, const BufferIterator& end)
{
kak_assert(begin.is_valid());
- m_first = begin;
- if (m_first >= m_buffer.end())
- m_first = utf8::previous(m_buffer.end());
- m_last = m_first;
+ m_ranges.update_erase(begin.coord(), end.coord());
+ auto pos = begin;
+ if (pos >= buffer().end())
+ pos = utf8::previous(buffer().end());
+
+ auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin,
+ [](const BufferIterator& it, const Selection& sel)
+ { return it < sel.begin(); });
+ m_ranges.emplace(it, pos, pos);
}
-
- const BufferIterator& first() const { return m_first; }
- const BufferIterator& last() const { return m_last; }
+ SelectionList& ranges() { return m_ranges; }
private:
- BufferIterator m_first;
- BufferIterator m_last;
- Buffer& m_buffer;
+ SelectionList m_ranges;
};
bool Editor::undo()
{
- LastModifiedRangeListener listener(buffer());
+ ModifiedRangesListener listener(buffer());
bool res = m_buffer->undo();
- if (res)
+ if (res and not listener.ranges().empty())
{
- m_selections = SelectionList{ {listener.first(), listener.last()} };
- m_main_sel = 0;
+ m_selections = std::move(listener.ranges());
+ m_main_sel = m_selections.size() - 1;
+ sort_and_merge_overlapping<true>(m_selections, m_main_sel);
}
check_invariant();
return res;
@@ -390,12 +399,13 @@ bool Editor::undo()
bool Editor::redo()
{
- LastModifiedRangeListener listener(buffer());
+ ModifiedRangesListener listener(buffer());
bool res = m_buffer->redo();
- if (res)
+ if (res and not listener.ranges().empty())
{
- m_selections = SelectionList{ {listener.first(), listener.last()} };
- m_main_sel = 0;
+ m_selections = std::move(listener.ranges());
+ m_main_sel = m_selections.size() - 1;
+ sort_and_merge_overlapping<true>(m_selections, m_main_sel);
}
check_invariant();
return res;