Fix, cleanup and refactor compute_modifications
This commit is contained in:
parent
a7540962cc
commit
695c85f451
|
@ -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> compute_modifications(memoryview<Buffer::Change> changes)
|
||||||
{
|
{
|
||||||
std::vector<Modification> res;
|
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;
|
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 += change.end.line - change.begin.line;
|
||||||
|
|
||||||
modif.num_added.line += num_added.line;
|
|
||||||
|
|
||||||
if (change.begin.line == last_line)
|
if (change.begin.line == last_line)
|
||||||
{
|
{
|
||||||
if (change.end.line == change.begin.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
|
else
|
||||||
num_added.column = change.end.column - modif.num_added.column;
|
modif.num_added.column = change.end.column;
|
||||||
|
|
||||||
modif.num_added.column += num_added.column;
|
|
||||||
kak_assert(modif.num_added.column >= 0);
|
kak_assert(modif.num_added.column >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = next; it != res.end(); ++it)
|
for (auto it = next; it != res.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->new_coord.line == change.begin.line and it->num_added.line == 0)
|
if (it->new_coord.line == change.begin.line)
|
||||||
it->new_coord.column += num_added.column;
|
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
|
else
|
||||||
|
@ -83,7 +141,7 @@ std::vector<Modification> compute_modifications(memoryview<Buffer::Change> chang
|
||||||
for (auto it = next; it != delend; ++it)
|
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_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);
|
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)
|
for (auto it = next; it != res.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->new_coord.line == change.end.line and it->num_added.line == 0)
|
if (it->new_coord.line == change.end.line)
|
||||||
it->new_coord.column -= num_removed.column;
|
it->new_coord.column += change.begin.column - change.end.column;
|
||||||
it->new_coord.line -= num_removed.line;
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,4 +199,17 @@ std::vector<Modification> compute_modifications(const Buffer& buffer, size_t tim
|
||||||
return compute_modifications(buffer.changes_since(timestamp));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,74 +15,19 @@ struct Modification
|
||||||
ByteCoord num_removed;
|
ByteCoord num_removed;
|
||||||
ByteCoord num_added;
|
ByteCoord num_added;
|
||||||
|
|
||||||
ByteCoord added_end() const
|
ByteCoord added_end() const;
|
||||||
{
|
ByteCoord removed_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 get_old_coord(ByteCoord coord) const
|
ByteCoord get_old_coord(ByteCoord coord) const;
|
||||||
{
|
ByteCoord get_new_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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Modification> compute_modifications(const Buffer& buffer, size_t timestamp);
|
std::vector<Modification> compute_modifications(const Buffer& buffer, size_t timestamp);
|
||||||
std::vector<Modification> compute_modifications(memoryview<Buffer::Change> changes);
|
std::vector<Modification> compute_modifications(memoryview<Buffer::Change> changes);
|
||||||
|
|
||||||
|
ByteCoord update_pos(memoryview<Modification> modifs, ByteCoord pos);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // modification_hh_INCLUDED
|
#endif // modification_hh_INCLUDED
|
||||||
|
|
|
@ -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);
|
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()
|
void SelectionList::update()
|
||||||
{
|
{
|
||||||
if (m_timestamp == m_buffer->timestamp())
|
if (m_timestamp == m_buffer->timestamp())
|
||||||
|
@ -163,6 +150,7 @@ void SelectionList::update()
|
||||||
sel.cursor() = cursor;
|
sel.cursor() = cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merge_overlapping(overlaps);
|
||||||
check_invariant();
|
check_invariant();
|
||||||
|
|
||||||
m_timestamp = m_buffer->timestamp();
|
m_timestamp = m_buffer->timestamp();
|
||||||
|
|
|
@ -153,6 +153,16 @@ void test_modification()
|
||||||
auto pos = modif.get_new_coord({7, 10});
|
auto pos = modif.get_new_coord({7, 10});
|
||||||
kak_assert(pos == ByteCoord{7 COMMA 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<Buffer::Change> change = {
|
std::vector<Buffer::Change> change = {
|
||||||
{ Buffer::Change::Insert, {1, 0}, {5, 161}, false },
|
{ 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_added == ByteCoord{34 COMMA 0});
|
||||||
kak_assert(modif.num_removed == ByteCoord{0 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,
|
Buffer buffer("test", Buffer::Flags::None,
|
||||||
{ "tchou mutch\n",
|
{ "tchou mutch\n",
|
||||||
|
@ -190,10 +227,8 @@ void test_modification()
|
||||||
kak_assert(modif.new_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_added == ByteCoord{1 COMMA 7});
|
||||||
kak_assert(modif.num_removed == ByteCoord{3 COMMA 0});
|
kak_assert(modif.num_removed == ByteCoord{3 COMMA 0});
|
||||||
bool deleted;
|
auto new_coord = modif.get_new_coord({1, 10});
|
||||||
auto new_coord = modif.get_new_coord({1, 10}, deleted);
|
|
||||||
kak_assert(new_coord == ByteCoord{1 COMMA 7});
|
kak_assert(new_coord == ByteCoord{1 COMMA 7});
|
||||||
kak_assert(deleted);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto& modif = modifs[1];
|
auto& modif = modifs[1];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user