summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-05-22 09:52:22 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-05-24 02:14:28 +0100
commit695c85f4513241c55296a37d2cf6cf0cd25dbecf (patch)
tree007404cc54a173a8478f4954037e394ca445ec80
parenta7540962cc90266f4f46858184b89f048364f9b2 (diff)
Fix, cleanup and refactor compute_modifications
-rw-r--r--src/modification.cc117
-rw-r--r--src/modification.hh69
-rw-r--r--src/selection.cc14
-rw-r--r--src/unit_tests.cc41
4 files changed, 148 insertions, 93 deletions
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<Modification> compute_modifications(memoryview<Buffer::Change> changes)
{
std::vector<Modification> res;
@@ -45,27 +103,27 @@ std::vector<Modification> compute_modifications(memoryview<Buffer::Change> 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;
-
- it->new_coord.line += num_added.line;
+ 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
@@ -83,7 +141,7 @@ std::vector<Modification> compute_modifications(memoryview<Buffer::Change> 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<Modification> compute_modifications(memoryview<Buffer::Change> 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<Modification> compute_modifications(const Buffer& buffer, size_t tim
return compute_modifications(buffer.changes_since(timestamp));
}
+ByteCoord update_pos(memoryview<Modification> 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<Modification> compute_modifications(const Buffer& buffer, size_t timestamp);
std::vector<Modification> compute_modifications(memoryview<Buffer::Change> changes);
+ByteCoord update_pos(memoryview<Modification> 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<Selection>& sels, ByteCoord begin, ByteCoord end,
on_buffer_change<UpdateErase>(sels, begin, end, at_end, end.line);
}
-static ByteCoord update_pos(memoryview<Modification> 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
@@ -154,6 +154,16 @@ void test_modification()
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<Buffer::Change> change = {
{ Buffer::Change::Insert, {1, 0}, {5, 161}, false },
{ Buffer::Change::Insert, {5, 161}, {30, 0}, 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<Buffer::Change> 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<Buffer::Change> 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];