Move Editor::{undo,redo} to free functions in normal.cc

This commit is contained in:
Maxime Coste 2013-12-15 19:51:09 +00:00
parent cb9384f8a7
commit 8047cc97d3
3 changed files with 69 additions and 71 deletions

View File

@ -24,72 +24,6 @@ std::vector<String> Editor::selections_content() const
return contents; 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 void Editor::check_invariant() const
{ {
#ifdef KAK_DEBUG #ifdef KAK_DEBUG

View File

@ -30,9 +30,6 @@ public:
SelectionList& selections() { return m_selections; } SelectionList& selections() { return m_selections; }
std::vector<String> selections_content() const; std::vector<String> selections_content() const;
bool undo();
bool redo();
private: private:
friend struct scoped_edition; friend struct scoped_edition;
friend class InputModes::Insert; friend class InputModes::Insert;

View File

@ -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<typename T> template<typename T>
class Repeated class Repeated
{ {
@ -1225,8 +1292,8 @@ KeyMap keymap =
{ '*', use_selection_as_search_pattern<true> }, { '*', use_selection_as_search_pattern<true> },
{ alt('*'), use_selection_as_search_pattern<false> }, { alt('*'), use_selection_as_search_pattern<false> },
{ 'u', repeated([](Context& context, int) { if (not context.editor().undo()) context.print_status({ "nothing left to undo", get_color("Information") }); }) }, { 'u', undo },
{ 'U', repeated([](Context& context, int) { if (not context.editor().redo()) context.print_status({ "nothing left to redo", get_color("Information") }); }) }, { 'U', redo },
{ alt('i'), select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd | ObjectFlags::Inner> }, { alt('i'), select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd | ObjectFlags::Inner> },
{ alt('a'), select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd> }, { alt('a'), select_object<ObjectFlags::ToBegin | ObjectFlags::ToEnd> },