From 9870ac22f6a22cc9a87a98a662f1e442500ca256 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 26 May 2014 21:09:12 +0100 Subject: [PATCH] Remove Modification Lets consider that as a failed experiment. You see, I learned something today, for a complicated problem, it is important to keep as much knowledge of the exact problem as possible. the Modification approach failed because it tried to solve the general problem, which is quite complex. The new approach, which keeps the knowledge that selections are sorted is much simpler and faster (see f49bec802157fc592bc6e35755807c6c3a531e78). --- src/modification.cc | 232 -------------------------------------------- src/modification.hh | 33 ------- src/normal.cc | 1 - src/unit_tests.cc | 141 --------------------------- 4 files changed, 407 deletions(-) delete mode 100644 src/modification.cc delete mode 100644 src/modification.hh diff --git a/src/modification.cc b/src/modification.cc deleted file mode 100644 index ba22a373..00000000 --- a/src/modification.cc +++ /dev/null @@ -1,232 +0,0 @@ -#include "modification.hh" - -#include "buffer.hh" - -namespace Kakoune -{ - -namespace -{ - -ByteCount change_added_column(const Buffer::Change& change) -{ - kak_assert(change.type == Buffer::Change::Insert); - if (change.begin.line == change.end.line) - return change.end.column - change.begin.column; - else - return change.end.column; -} - -} - -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; - for (auto& change : changes) - { - auto pos = std::upper_bound(res.begin(), res.end(), change.begin, - [](const ByteCoord& l, const Modification& c) - { return l < c.new_coord; }); - - if (pos != res.begin()) - { - auto& prev = *(pos-1); - if (change.begin <= prev.added_end()) - --pos; - else - pos = res.insert(pos, {prev.get_old_coord(change.begin), change.begin, {}, {}}); - } - else - pos = res.insert(pos, {change.begin, change.begin, {}, {}}); - - auto& modif = *pos; - auto next = pos + 1; - if (change.type == Buffer::Change::Insert) - { - const LineCount last_line = modif.new_coord.line + modif.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) - modif.num_added.column += change.end.column - change.begin.column; - else - 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) - it->new_coord.column += change.end.column - change.begin.column; - it->new_coord.line += change.end.line - change.begin.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 - { - ByteCoord num_removed = { change.end.line - change.begin.line, 0 }; - if (num_removed.line != 0) - num_removed.column = change.end.column; - else - num_removed.column = change.end.column - change.begin.column; - - ByteCoord num_added; - - // merge modifications lying in the erased range. - auto delend = std::upper_bound(next, res.end(), change.end, - [](const ByteCoord& l, const Modification& c) - { return l < c.new_coord; }); - - for (auto it = next; it != delend; ++it) - { - { - LineCount removed_from_it = change.end.line - it->new_coord.line; - num_removed.line += it->num_removed.line - std::min(removed_from_it, it->num_added.line); - num_added.line += std::max(0_line, it->num_added.line - removed_from_it); - } - - if (it->new_coord.line == change.end.line) - num_removed.column += it->num_removed.column; - if (it->new_coord.line + it->num_added.line == change.end.line) - { - ByteCount removed_from_added = std::min(num_removed.column, it->num_added.column); - num_added.column += std::max(0_byte, it->num_added.column - removed_from_added); - num_removed.column -= removed_from_added; - } - if (it->new_coord.line == change.begin.line) - num_removed.column += it->new_coord.column - change.begin.column; - } - next = res.erase(next, delend); - - // update modification with changes - if (change.end.line == modif.new_coord.line + modif.num_added.line) - { - ByteCount removed_from_added = std::min(num_removed.column, modif.num_added.column); - modif.num_added.column = std::max(0_byte, modif.num_added.column - removed_from_added) + num_added.column; - modif.num_removed.column += num_removed.column - removed_from_added; - } - else if (change.end.line > modif.new_coord.line + modif.num_added.line) - { - modif.num_added.column = num_added.column; - modif.num_removed.column = num_removed.column; - } - if (change.begin.line == modif.new_coord.line) - modif.num_added.column += change.begin.column - modif.new_coord.column; - - { - LineCount change_pos_in_modif = change.begin.line - modif.new_coord.line; - LineCount removed_from_added = std::min(num_removed.line, modif.num_added.line - change_pos_in_modif); - modif.num_added.line = std::max(0_line, modif.num_added.line - removed_from_added) + num_added.line; - modif.num_removed.line += num_removed.line - removed_from_added; - } - - for (auto it = next; it != res.end(); ++it) - { - 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; -} - -std::vector compute_modifications(const Buffer& buffer, size_t timestamp) -{ - 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 deleted file mode 100644 index 2b972a84..00000000 --- a/src/modification.hh +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef modification_hh_INCLUDED -#define modification_hh_INCLUDED - -#include "coord.hh" -#include "utils.hh" -#include "buffer.hh" - -namespace Kakoune -{ - -struct Modification -{ - ByteCoord old_coord; - ByteCoord new_coord; - ByteCoord num_removed; - ByteCoord num_added; - - ByteCoord added_end() const; - ByteCoord removed_end() const; - - 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/normal.cc b/src/normal.cc index 62cfb864..2e7e166e 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -17,7 +17,6 @@ #include "user_interface.hh" #include "utf8_iterator.hh" #include "debug.hh" -#include "modification.hh" namespace Kakoune { diff --git a/src/unit_tests.cc b/src/unit_tests.cc index c7569804..85038d06 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -4,8 +4,6 @@ #include "selectors.hh" #include "word_db.hh" -#include "modification.hh" - using namespace Kakoune; void test_buffer() @@ -144,144 +142,6 @@ void test_keys() kak_assert(keys == parsed_keys); } -void test_modification() -{ - { - Modification modif = { {5, 10}, {5, 10}, {0, 0}, {4, 17} }; - auto pos = modif.get_new_coord({5, 10}); - kak_assert(pos == ByteCoord{9 COMMA 17}); - } - { - Modification modif = { {7, 10}, {7, 10}, {0, 5}, {0, 0} }; - 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 }, - { Buffer::Change::Insert, {5, 161}, {30, 0}, false }, - { Buffer::Change::Insert, {30, 0}, {35, 0}, false }, - }; - auto modifs = compute_modifications(change); - kak_assert(modifs.size() == 1); - auto& modif = modifs[0]; - kak_assert(modif.old_coord == ByteCoord{1 COMMA 0}); - kak_assert(modif.new_coord == ByteCoord{1 COMMA 0}); - 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}); - } - { - std::vector change = { - { Buffer::Change::Insert, {1, 10}, {2, 0}, false }, - { Buffer::Change::Erase, {1, 20}, {2, 10}, false }, - }; - auto modifs = compute_modifications(change); - kak_assert(modifs.size() == 1); - auto& modif = modifs[0]; - kak_assert(modif.old_coord == ByteCoord{1 COMMA 10}); - kak_assert(modif.new_coord == ByteCoord{1 COMMA 10}); - kak_assert(modif.num_added == ByteCoord{0 COMMA 10}); - kak_assert(modif.num_removed == ByteCoord{0 COMMA 10}); - } - { - std::vector change = { - { Buffer::Change::Insert, {1, 10}, {2, 20}, false }, - { Buffer::Change::Erase, {1, 5}, {2, 10}, false }, - }; - auto modifs = compute_modifications(change); - kak_assert(modifs.size() == 1); - auto& modif = modifs[0]; - kak_assert(modif.old_coord == ByteCoord{1 COMMA 5}); - kak_assert(modif.new_coord == ByteCoord{1 COMMA 5}); - kak_assert(modif.num_added == ByteCoord{0 COMMA 10}); - kak_assert(modif.num_removed == ByteCoord{0 COMMA 5}); - } - { - std::vector change = { - { Buffer::Change::Insert, {1, 10}, {2, 20}, false }, - { Buffer::Change::Erase, {1, 5}, {2, 10}, false }, - { Buffer::Change::Erase, {1, 10}, {2, 0}, false }, - }; - auto modifs = compute_modifications(change); - kak_assert(modifs.size() == 1); - auto& modif = modifs[0]; - kak_assert(modif.old_coord == ByteCoord{1 COMMA 5}); - kak_assert(modif.new_coord == ByteCoord{1 COMMA 5}); - kak_assert(modif.num_added == ByteCoord{0 COMMA 5}); - kak_assert(modif.num_removed == ByteCoord{1 COMMA 0}); - } - - Buffer buffer("test", Buffer::Flags::None, - { "tchou mutch\n", - "tchou kanaky tchou\n", - "\n", - "tchaa tchaa\n", - "allo\n"}); - - size_t timestamp = buffer.timestamp(); - - buffer.erase(buffer.iterator_at({0,0}), buffer.iterator_at({3,0})); - buffer.insert(buffer.iterator_at({0,0}), "youuhou\nniahaha"); - - buffer.insert(buffer.iterator_at({2,4}), "yeehaah\n"); - - auto modifs = compute_modifications(buffer, timestamp); - kak_assert(modifs.size() == 2); - { - auto& modif = modifs[0]; - kak_assert(modif.old_coord == ByteCoord{0 COMMA 0}); - 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}); - auto new_coord = modif.get_new_coord({1, 10}); - kak_assert(new_coord == ByteCoord{1 COMMA 7}); - } - { - auto& modif = modifs[1]; - kak_assert(modif.old_coord == ByteCoord{4 COMMA 4}); - kak_assert(modif.new_coord == ByteCoord{2 COMMA 4}); - kak_assert(modif.num_added == ByteCoord{1 COMMA 0}); - kak_assert(modif.num_removed == ByteCoord{0 COMMA 0}); - } -} - void run_unit_tests() { test_utf8(); @@ -289,6 +149,5 @@ void run_unit_tests() test_keys(); test_buffer(); test_undo_group_optimizer(); - test_modification(); test_word_db(); }