diff --git a/src/modification.cc b/src/modification.cc index b5e91c1f..2539ea3a 100644 --- a/src/modification.cc +++ b/src/modification.cc @@ -19,6 +19,64 @@ ByteCount change_added_column(const Buffer::Change& change) } +ByteCoord Modification::added_end() const +{ + if (num_added.line) + return { new_coord.line + num_added.line, num_added.column }; + else + return { new_coord.line, new_coord.column + num_added.column }; +} + +ByteCoord Modification::removed_end() const +{ + if (num_removed.line) + return { old_coord.line + num_removed.line, num_removed.column }; + else + return { old_coord.line, old_coord.column + num_removed.column }; +} + +ByteCoord Modification::get_old_coord(ByteCoord coord) const +{ + Modification inverse = { new_coord, old_coord, num_added, num_removed }; + return inverse.get_new_coord(coord); +} + +ByteCoord Modification::get_new_coord(ByteCoord coord) const +{ + if (coord < old_coord) + return coord; + + // apply remove + if (coord < removed_end()) + coord = old_coord; + else if (coord.line == old_coord.line + num_removed.line) + { + coord.line = old_coord.line; + if (num_removed.line != 0) + coord.column += old_coord.column; + coord.column -= num_removed.column; + } + else + coord.line -= num_removed.line; + + // apply move + coord.line += new_coord.line - old_coord.line; + if (coord.line == new_coord.line) + coord.column += new_coord.column - old_coord.column; + + // apply add + if (coord.line == new_coord.line) + { + if (num_added.line == 0) + coord.column += num_added.column; + else + coord.column += num_added.column - new_coord.column; + } + coord.line += num_added.line; + + return coord; +} + std::vector compute_modifications(memoryview changes) { std::vector res; @@ -45,27 +103,27 @@ std::vector compute_modifications(memoryview chang { const LineCount last_line = modif.new_coord.line + modif.num_added.line; - ByteCoord num_added = { change.end.line - change.begin.line, 0 }; - - modif.num_added.line += num_added.line; + modif.num_added.line += change.end.line - change.begin.line; if (change.begin.line == last_line) { if (change.end.line == change.begin.line) - num_added.column = change.end.column - change.begin.column; + modif.num_added.column += change.end.column - change.begin.column; else - num_added.column = change.end.column - modif.num_added.column; - - modif.num_added.column += num_added.column; + modif.num_added.column = change.end.column; kak_assert(modif.num_added.column >= 0); } for (auto it = next; it != res.end(); ++it) { - if (it->new_coord.line == change.begin.line and it->num_added.line == 0) - it->new_coord.column += num_added.column; + if (it->new_coord.line == change.begin.line) + it->new_coord.column += change.end.column - change.begin.column; + it->new_coord.line += change.end.line - change.begin.line; - it->new_coord.line += num_added.line; +#ifdef KAK_DEBUG + auto ref_new_coord = (it-1)->get_new_coord(it->old_coord); + kak_assert(it->new_coord == ref_new_coord); +#endif } } else @@ -83,7 +141,7 @@ std::vector compute_modifications(memoryview chang for (auto it = next; it != delend; ++it) { { - LineCount removed_from_it = (change.begin.line + num_removed.line - it->new_coord.line); + LineCount removed_from_it = change.end.line - it->new_coord.line; modif.num_removed.line += it->num_removed.line - std::min(removed_from_it, it->num_added.line); modif.num_added.line += std::max(0_line, it->num_added.line - removed_from_it); } @@ -111,12 +169,28 @@ std::vector compute_modifications(memoryview chang for (auto it = next; it != res.end(); ++it) { - if (it->new_coord.line == change.end.line and it->num_added.line == 0) - it->new_coord.column -= num_removed.column; - it->new_coord.line -= num_removed.line; + if (it->new_coord.line == change.end.line) + it->new_coord.column += change.begin.column - change.end.column; + it->new_coord.line += change.begin.line - change.end.line; + +#ifdef KAK_DEBUG + auto ref_new_coord = (it-1)->get_new_coord(it->old_coord); + kak_assert(it->new_coord == ref_new_coord); +#endif } } } + +#ifdef KAK_DEBUG + for (size_t i = 0; i+1 < res.size(); ++i) + { + auto old_coord = res[i].get_old_coord(res[i+1].new_coord); + kak_assert(res[i+1].old_coord == old_coord); + auto new_coord = res[i].get_new_coord(res[i+1].old_coord); + kak_assert(res[i+1].new_coord == new_coord); + } +#endif + return res; } @@ -125,4 +199,17 @@ std::vector compute_modifications(const Buffer& buffer, size_t tim return compute_modifications(buffer.changes_since(timestamp)); } +ByteCoord update_pos(memoryview modifs, ByteCoord pos) +{ + auto modif_it = std::upper_bound(modifs.begin(), modifs.end(), pos, + [](const ByteCoord& c, const Modification& m) + { return c < m.old_coord; }); + if (modif_it != modifs.begin()) + { + auto& prev = *(modif_it-1); + return prev.get_new_coord(pos); + } + return pos; +} + } diff --git a/src/modification.hh b/src/modification.hh index 103a7520..2b972a84 100644 --- a/src/modification.hh +++ b/src/modification.hh @@ -15,74 +15,19 @@ struct Modification ByteCoord num_removed; ByteCoord num_added; - ByteCoord added_end() const - { - if (num_added.line) - return { new_coord.line + num_added.line, num_added.column }; - else - return { new_coord.line, new_coord.column + num_added.column }; - } + ByteCoord added_end() const; + ByteCoord removed_end() const; - ByteCoord get_old_coord(ByteCoord coord) const - { - if (coord.line == new_coord.line) - { - if (num_added.line == 0) - coord.column -= new_coord.column - old_coord.column + num_added.column - num_removed.column; - else - coord.column -= num_added.column - num_removed.column; - } - coord.line -= new_coord.line - old_coord.line + num_added.line - num_removed.line; - return coord; - } - - ByteCoord get_new_coord(ByteCoord coord, bool& deleted) const - { - deleted = false; - if (coord < old_coord) - return coord; - - // apply remove - if (coord.line < old_coord.line + num_removed.line or - (coord.line == old_coord.line + num_removed.line and - coord.column < old_coord.column + num_removed.column)) - { - deleted = true; - coord = old_coord; - } - else if (coord.line == old_coord.line + num_removed.line) - { - coord.line = old_coord.line; - coord.column -= num_removed.column; - } - - // apply move - coord.line += new_coord.line - old_coord.line; - coord.column += new_coord.column - old_coord.column; - - // apply add - if (coord.line == new_coord.line) - { - if (num_added.line == 0) - coord.column += num_added.column; - else - coord.column += num_added.column - new_coord.column; - } - coord.line += num_added.line; - - return coord; - } - - ByteCoord get_new_coord(ByteCoord coord) const - { - bool dummy; - return get_new_coord(coord, dummy); - } + ByteCoord get_old_coord(ByteCoord coord) const; + ByteCoord get_new_coord(ByteCoord coord) const; }; std::vector compute_modifications(const Buffer& buffer, size_t timestamp); std::vector compute_modifications(memoryview changes); +ByteCoord update_pos(memoryview modifs, ByteCoord pos); + + } #endif // modification_hh_INCLUDED diff --git a/src/selection.cc b/src/selection.cc index 6b00dc54..f2126975 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -133,19 +133,6 @@ void update_erase(std::vector& sels, ByteCoord begin, ByteCoord end, on_buffer_change(sels, begin, end, at_end, end.line); } -static ByteCoord update_pos(memoryview modifs, ByteCoord pos) -{ - auto modif_it = std::upper_bound(modifs.begin(), modifs.end(), pos, - [](const ByteCoord& c, const Modification& m) - { return c < m.old_coord; }); - if (modif_it != modifs.begin()) - { - auto& prev = *(modif_it-1); - return prev.get_new_coord(pos); - } - return pos; -} - void SelectionList::update() { if (m_timestamp == m_buffer->timestamp()) @@ -163,6 +150,7 @@ void SelectionList::update() sel.cursor() = cursor; } + merge_overlapping(overlaps); check_invariant(); m_timestamp = m_buffer->timestamp(); diff --git a/src/unit_tests.cc b/src/unit_tests.cc index fa21b736..6bae7a80 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -153,6 +153,16 @@ void test_modification() auto pos = modif.get_new_coord({7, 10}); kak_assert(pos == ByteCoord{7 COMMA 10}); } + { + Modification modif = { {8, 0}, {8, 0}, {1, 0}, {1, 0} }; + auto pos = modif.get_new_coord({12, 31}); + kak_assert(pos == ByteCoord{12 COMMA 31}); + } + { + Modification modif = { {0, 7}, {0, 8}, {0, 0}, {0, 1} }; + auto pos = modif.get_new_coord({1, 0}); + kak_assert(pos == ByteCoord{1 COMMA 0}); + } { std::vector change = { { Buffer::Change::Insert, {1, 0}, {5, 161}, false }, @@ -167,6 +177,33 @@ void test_modification() kak_assert(modif.num_added == ByteCoord{34 COMMA 0}); kak_assert(modif.num_removed == ByteCoord{0 COMMA 0}); } + { + std::vector change = { + { Buffer::Change::Insert, {1, 20}, {2, 0}, false }, + { Buffer::Change::Insert, {1, 10}, {2, 0}, false }, + { Buffer::Change::Insert, {1, 0}, {2, 0}, false }, + }; + auto modifs = compute_modifications(change); + kak_assert(modifs.size() == 3); + auto& modif = modifs[2]; + kak_assert(modif.old_coord == ByteCoord{1 COMMA 20}); + kak_assert(modif.new_coord == ByteCoord{3 COMMA 10}); + kak_assert(modif.num_added == ByteCoord{1 COMMA 0}); + kak_assert(modif.num_removed == ByteCoord{0 COMMA 0}); + } + { + std::vector change = { + { Buffer::Change::Erase, {1, 10}, {2, 0}, false }, + { Buffer::Change::Erase, {0, 10}, {1, 0}, false }, + }; + auto modifs = compute_modifications(change); + kak_assert(modifs.size() == 2); + auto& modif = modifs[1]; + kak_assert(modif.old_coord == ByteCoord{1 COMMA 10}); + kak_assert(modif.new_coord == ByteCoord{0 COMMA 20}); + kak_assert(modif.num_added == ByteCoord{0 COMMA 0}); + kak_assert(modif.num_removed == ByteCoord{1 COMMA 0}); + } Buffer buffer("test", Buffer::Flags::None, { "tchou mutch\n", @@ -190,10 +227,8 @@ void test_modification() kak_assert(modif.new_coord == ByteCoord{0 COMMA 0}); kak_assert(modif.num_added == ByteCoord{1 COMMA 7}); kak_assert(modif.num_removed == ByteCoord{3 COMMA 0}); - bool deleted; - auto new_coord = modif.get_new_coord({1, 10}, deleted); + auto new_coord = modif.get_new_coord({1, 10}); kak_assert(new_coord == ByteCoord{1 COMMA 7}); - kak_assert(deleted); } { auto& modif = modifs[1];