diff --git a/src/editor.cc b/src/editor.cc index 12c65096..3655c0b4 100644 --- a/src/editor.cc +++ b/src/editor.cc @@ -24,72 +24,6 @@ std::vector Editor::selections_content() const return contents; } -class ModifiedRangesListener : public BufferChangeListener_AutoRegister -{ -public: - ModifiedRangesListener(Buffer& buffer) - : BufferChangeListener_AutoRegister(buffer) {} - - void on_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end) - { - m_ranges.update_insert(buffer, begin, end); - auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin, - [](BufferCoord c, const Selection& sel) - { return c < sel.min(); }); - m_ranges.emplace(it, begin, buffer.char_prev(end)); - } - - void on_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end) - { - m_ranges.update_erase(buffer, begin, end); - auto pos = std::min(begin, buffer.back_coord()); - auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), pos, - [](BufferCoord c, const Selection& sel) - { return c < sel.min(); }); - m_ranges.emplace(it, pos, pos); - } - SelectionList& ranges() { return m_ranges; } - -private: - SelectionList m_ranges; -}; - -inline bool touches(const Buffer& buffer, const Range& lhs, const Range& rhs) -{ - return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min() - : lhs.min() <= buffer.char_next(rhs.max()); -} - -bool Editor::undo() -{ - using namespace std::placeholders; - ModifiedRangesListener listener(buffer()); - bool res = m_buffer->undo(); - if (res and not listener.ranges().empty()) - { - m_selections = std::move(listener.ranges()); - m_selections.set_main_index(m_selections.size() - 1); - m_selections.merge_overlapping(std::bind(touches, std::ref(buffer()), _1, _2)); - } - check_invariant(); - return res; -} - -bool Editor::redo() -{ - using namespace std::placeholders; - ModifiedRangesListener listener(buffer()); - bool res = m_buffer->redo(); - if (res and not listener.ranges().empty()) - { - m_selections = std::move(listener.ranges()); - m_selections.set_main_index(m_selections.size() - 1); - m_selections.merge_overlapping(std::bind(touches, std::ref(buffer()), _1, _2)); - } - check_invariant(); - return res; -} - void Editor::check_invariant() const { #ifdef KAK_DEBUG diff --git a/src/editor.hh b/src/editor.hh index d7e1a1c2..d808fe76 100644 --- a/src/editor.hh +++ b/src/editor.hh @@ -30,9 +30,6 @@ public: SelectionList& selections() { return m_selections; } std::vector selections_content() const; - bool undo(); - bool redo(); - private: friend struct scoped_edition; friend class InputModes::Insert; diff --git a/src/normal.cc b/src/normal.cc index 1b922275..52ca9694 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1094,6 +1094,73 @@ void align_indent(Context& context, int selection) } } +class ModifiedRangesListener : public BufferChangeListener_AutoRegister +{ +public: + ModifiedRangesListener(Buffer& buffer) + : BufferChangeListener_AutoRegister(buffer) {} + + void on_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end) + { + m_ranges.update_insert(buffer, begin, end); + auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), begin, + [](BufferCoord c, const Selection& sel) + { return c < sel.min(); }); + m_ranges.emplace(it, begin, buffer.char_prev(end)); + } + + void on_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end) + { + m_ranges.update_erase(buffer, begin, end); + auto pos = std::min(begin, buffer.back_coord()); + auto it = std::upper_bound(m_ranges.begin(), m_ranges.end(), pos, + [](BufferCoord c, const Selection& sel) + { return c < sel.min(); }); + m_ranges.emplace(it, pos, pos); + } + SelectionList& ranges() { return m_ranges; } + +private: + SelectionList m_ranges; +}; + +inline bool touches(const Buffer& buffer, const Range& lhs, const Range& rhs) +{ + return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min() + : lhs.min() <= buffer.char_next(rhs.max()); +} + +void undo(Context& context, int) +{ + ModifiedRangesListener listener(context.buffer()); + bool res = context.buffer().undo(); + if (res and not listener.ranges().empty()) + { + auto& selections = context.selections(); + selections = std::move(listener.ranges()); + selections.set_main_index(selections.size() - 1); + selections.merge_overlapping(std::bind(touches, std::ref(context.buffer()), _1, _2)); + } + else if (not res) + context.print_status({ "nothing left to undo", get_color("Information") }); +} + +void redo(Context& context, int) +{ + using namespace std::placeholders; + ModifiedRangesListener listener(context.buffer()); + bool res = context.buffer().redo(); + if (res and not listener.ranges().empty()) + { + auto& selections = context.selections(); + selections = std::move(listener.ranges()); + selections.set_main_index(selections.size() - 1); + selections.merge_overlapping(std::bind(touches, std::ref(context.buffer()), _1, _2)); + } + else if (not res) + context.print_status({ "nothing left to redo", get_color("Information") }); +} + template class Repeated { @@ -1225,8 +1292,8 @@ KeyMap keymap = { '*', use_selection_as_search_pattern }, { alt('*'), use_selection_as_search_pattern }, - { 'u', repeated([](Context& context, int) { if (not context.editor().undo()) context.print_status({ "nothing left to undo", get_color("Information") }); }) }, - { 'U', repeated([](Context& context, int) { if (not context.editor().redo()) context.print_status({ "nothing left to redo", get_color("Information") }); }) }, + { 'u', undo }, + { 'U', redo }, { alt('i'), select_object }, { alt('a'), select_object },