Support counts for undo/redo

This commit is contained in:
Maxime Coste 2016-07-20 20:20:03 +01:00
parent 3edd2c127c
commit 03a4b3c73f
3 changed files with 25 additions and 21 deletions

View File

@ -310,31 +310,38 @@ void Buffer::commit_undo_group()
m_history_cursor = node; m_history_cursor = node;
} }
bool Buffer::undo() noexcept bool Buffer::undo(size_t count) noexcept
{ {
commit_undo_group(); commit_undo_group();
if (not m_history_cursor->parent) if (not m_history_cursor->parent)
return false; return false;
for (const Modification& modification : m_history_cursor->undo_group | reverse()) while (count-- and m_history_cursor->parent)
apply_modification(modification.inverse()); {
for (const Modification& modification : m_history_cursor->undo_group | reverse())
apply_modification(modification.inverse());
m_history_cursor = m_history_cursor->parent;
}
m_history_cursor = m_history_cursor->parent;
return true; return true;
} }
bool Buffer::redo() noexcept bool Buffer::redo(size_t count) noexcept
{ {
if (not m_history_cursor->redo_child) if (not m_history_cursor->redo_child)
return false; return false;
kak_assert(m_current_undo_group.empty()); kak_assert(m_current_undo_group.empty());
m_history_cursor = m_history_cursor->redo_child.get(); while (count-- and m_history_cursor->redo_child)
{
m_history_cursor = m_history_cursor->redo_child.get();
for (const Modification& modification : m_history_cursor->undo_group) for (const Modification& modification : m_history_cursor->undo_group)
apply_modification(modification); apply_modification(modification);
}
return true; return true;
} }
@ -826,8 +833,8 @@ UnitTest test_undo{[]()
buffer.commit_undo_group(); buffer.commit_undo_group();
buffer.erase({2, 1}, {2, 5}); // change 5 buffer.erase({2, 1}, {2, 5}); // change 5
buffer.commit_undo_group(); buffer.commit_undo_group();
buffer.undo(); buffer.undo(2);
buffer.redo(); buffer.redo(2);
buffer.undo(); buffer.undo();
buffer.replace(2_line, buffer.end_coord(), "foo"); // change 6 buffer.replace(2_line, buffer.end_coord(), "foo"); // change 6
buffer.commit_undo_group(); buffer.commit_undo_group();

View File

@ -132,8 +132,8 @@ public:
void set_fs_timestamp(timespec ts); void set_fs_timestamp(timespec ts);
void commit_undo_group(); void commit_undo_group();
bool undo() noexcept; bool undo(size_t count = 1) noexcept;
bool redo() noexcept; bool redo(size_t count = 1) noexcept;
bool move_to(size_t history_id) noexcept; bool move_to(size_t history_id) noexcept;
String string(ByteCoord begin, ByteCoord end) const; String string(ByteCoord begin, ByteCoord end) const;

View File

@ -1414,37 +1414,34 @@ void restore_selections(Context& context, NormalParams params)
context.print_status({format("Restored selections from register '{}'", reg), get_face("Information")}); context.print_status({format("Restored selections from register '{}'", reg), get_face("Information")});
} }
void undo(Context& context, NormalParams) void undo(Context& context, NormalParams params)
{ {
Buffer& buffer = context.buffer(); Buffer& buffer = context.buffer();
size_t timestamp = buffer.timestamp(); size_t timestamp = buffer.timestamp();
bool res = buffer.undo(); if (buffer.undo(std::max(1, params.count)))
if (res)
{ {
auto ranges = compute_modified_ranges(buffer, timestamp); auto ranges = compute_modified_ranges(buffer, timestamp);
if (not ranges.empty()) if (not ranges.empty())
context.selections_write_only() = std::move(ranges); context.selections_write_only() = std::move(ranges);
context.selections().avoid_eol(); context.selections().avoid_eol();
} }
else if (not res) else
context.print_status({ "nothing left to undo", get_face("Information") }); context.print_status({ "nothing left to undo", get_face("Information") });
} }
void redo(Context& context, NormalParams) void redo(Context& context, NormalParams params)
{ {
using namespace std::placeholders; using namespace std::placeholders;
Buffer& buffer = context.buffer(); Buffer& buffer = context.buffer();
size_t timestamp = buffer.timestamp(); size_t timestamp = buffer.timestamp();
bool res = buffer.redo(); if (buffer.redo(std::max(1, params.count)))
if (res)
{ {
auto ranges = compute_modified_ranges(buffer, timestamp); auto ranges = compute_modified_ranges(buffer, timestamp);
if (not ranges.empty()) if (not ranges.empty())
context.selections_write_only() = std::move(ranges); context.selections_write_only() = std::move(ranges);
context.selections().avoid_eol(); context.selections().avoid_eol();
} }
else
else if (not res)
context.print_status({ "nothing left to redo", get_face("Information") }); context.print_status({ "nothing left to redo", get_face("Information") });
} }