diff --git a/src/buffer.cc b/src/buffer.cc index c2a04c2e..d84586cd 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -260,28 +260,31 @@ void Buffer::reload(StringView data, timespec fs_timestamp) Vector diff; for_each_diff(m_lines.begin(), m_lines.size(), parsed_lines.lines.begin(), parsed_lines.lines.size(), - [&diff](DiffOp op, int len, int posB) - { diff.push_back({op, len, posB}); }, + [&diff](DiffOp op, int len) + { diff.push_back({op, len}); }, [](const StringDataPtr& lhs, const StringDataPtr& rhs) { return lhs->strview() == rhs->strview(); }); auto it = m_lines.begin(); + auto new_it = parsed_lines.lines.begin(); for (auto& d : diff) { if (d.op == DiffOp::Keep) + { it += d.len; + new_it += d.len; + } else if (d.op == DiffOp::Add) { const LineCount cur_line = (int)(it - m_lines.begin()); for (LineCount line = 0; line < d.len; ++line) - m_current_undo_group.push_back({ - Modification::Insert, cur_line + line, - parsed_lines.lines[(int)(d.posB + line)]}); + m_current_undo_group.push_back({Modification::Insert, cur_line + line, *(new_it + (int)line)}); - m_changes.push_back({ Change::Insert, cur_line, cur_line + d.len }); - m_lines.insert(it, parsed_lines.lines.begin() + d.posB, parsed_lines.lines.begin() + d.posB + d.len); + m_changes.push_back({Change::Insert, cur_line, cur_line + d.len}); + m_lines.insert(it, new_it, new_it + d.len); it = m_lines.begin() + (int)(cur_line + d.len); + new_it += d.len; } else if (d.op == DiffOp::Remove) { diff --git a/src/diff.hh b/src/diff.hh index 8d1abdc6..30a3884d 100644 --- a/src/diff.hh +++ b/src/diff.hh @@ -115,9 +115,9 @@ void find_diff_rec(IteratorA a, int begA, int endA, int* V1, int* V2, int cost_limit, Equal eq, OnDiff&& on_diff) { - auto on_diff_ifn = [&](DiffOp op, int len, int posB) { + auto on_diff_ifn = [&](DiffOp op, int len) { if (len != 0) - on_diff(op, len, posB); + on_diff(op, len); }; int prefix_len = 0; @@ -128,14 +128,14 @@ void find_diff_rec(IteratorA a, int begA, int endA, while (begA != endA and begB != endB and eq(a[endA-1], b[endB-1])) --endA, --endB, ++suffix_len; - on_diff_ifn(DiffOp::Keep, prefix_len, 0); + on_diff_ifn(DiffOp::Keep, prefix_len); const auto lenA = endA - begA, lenB = endB - begB; if (lenA == 0) - on_diff_ifn(DiffOp::Add, lenB, begB); + on_diff_ifn(DiffOp::Add, lenB); else if (lenB == 0) - on_diff_ifn(DiffOp::Remove, lenA, 0); + on_diff_ifn(DiffOp::Remove, lenA); else { auto snake = find_middle_snake(a + begA, lenA, b + begB, lenB, V1, V2, cost_limit, eq); @@ -146,30 +146,29 @@ void find_diff_rec(IteratorA a, int begA, int endA, V1, V2, cost_limit, eq, on_diff); if (snake.op == Snake::Add) - on_diff_ifn(DiffOp::Add, 1, begB + snake.y - 1); + on_diff_ifn(DiffOp::Add, 1); if (snake.op == Snake::Del) - on_diff_ifn(DiffOp::Remove, 1, 0); + on_diff_ifn(DiffOp::Remove, 1); - on_diff_ifn(DiffOp::Keep, snake.u - snake.x, 0); + on_diff_ifn(DiffOp::Keep, snake.u - snake.x); if (snake.op == Snake::RevAdd) - on_diff_ifn(DiffOp::Add, 1, begB + snake.v); + on_diff_ifn(DiffOp::Add, 1); if (snake.op == Snake::RevDel) - on_diff_ifn(DiffOp::Remove, 1, 0); + on_diff_ifn(DiffOp::Remove, 1); find_diff_rec(a, begA + snake.u + (int)(snake.op == Snake::RevDel), endA, b, begB + snake.v + (int)(snake.op == Snake::RevAdd), endB, V1, V2, cost_limit, eq, on_diff); } - on_diff_ifn(DiffOp::Keep, suffix_len, 0); + on_diff_ifn(DiffOp::Keep, suffix_len); } struct Diff { DiffOp op; int len; - int posB; }; template> @@ -181,18 +180,18 @@ void for_each_diff(IteratorA a, int N, IteratorB b, int M, OnDiff&& on_diff, Equ Diff last{}; find_diff_rec(a, 0, N, b, 0, M, &data[N+M], &data[max + N+M], cost_limit, eq, - [&last, &on_diff](DiffOp op, int len, int posB) { - if (last.op == op and (op != DiffOp::Add or last.posB + last.len == posB)) + [&last, &on_diff](DiffOp op, int len) { + if (last.op == op) last.len += len; else { - if (last.op != DiffOp{} or last.len != 0 or last.posB != 0) - on_diff(last.op, last.len, last.posB); - last = Diff{op, len, posB}; + if (last.len != 0) + on_diff(last.op, last.len); + last = Diff{op, len}; } }); - if (last.op != DiffOp{} or last.len != 0 or last.posB != 0) - on_diff(last.op, last.len, last.posB); + if (last.op != DiffOp{} or last.len != 0) + on_diff(last.op, last.len); } } diff --git a/src/normal.cc b/src/normal.cc index ddd88a8c..53e745e2 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -517,16 +517,18 @@ BufferCoord apply_diff(Buffer& buffer, BufferCoord pos, StringView before, Strin for_each_diff(lines_before.begin(), (int)lines_before.size(), lines_after.begin(), (int)lines_after.size(), - [&, posA = 0](DiffOp op, int len, int posB) mutable { + [&, posA = 0, posB = 0](DiffOp op, int len) mutable { switch (op) { case DiffOp::Keep: pos = buffer.advance(pos, byte_count(lines_before, posA, len)); posA += len; + posB += len; break; case DiffOp::Add: pos = buffer.insert(pos, {lines_after[posB].begin(), lines_after[posB + len - 1].end()}).end; + posB += len; break; case DiffOp::Remove: pos = buffer.erase(pos, buffer.advance(pos, byte_count(lines_before, posA, len))); diff --git a/src/unit_tests.cc b/src/unit_tests.cc index 5b693026..7c77d508 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -17,29 +17,29 @@ UnitTest test_utf8{[]() UnitTest test_diff{[]() { - struct Diff{DiffOp op; int len; int posB = 0;}; + struct Diff{DiffOp op; int len;}; auto check_diff = [](StringView a, StringView b, std::initializer_list diffs) { size_t count = 0; for_each_diff(a.begin(), (int)a.length(), b.begin(), (int)b.length(), - [&](DiffOp op, int len, int posB) { + [&](DiffOp op, int len) { kak_assert(count < diffs.size()); auto& d = diffs.begin()[count++]; - kak_assert(d.op == op and d.len == len and d.posB == posB); + kak_assert(d.op == op and d.len == len); }); kak_assert(count == diffs.size()); }; check_diff("a?", "!", {{DiffOp::Remove, 1}, {DiffOp::Add, 1}, {DiffOp::Remove, 1}}); check_diff("abcde", "cd", {{DiffOp::Remove, 2}, {DiffOp::Keep, 2}, {DiffOp::Remove, 1}}); - check_diff("abcd", "cdef", {{DiffOp::Remove, 2}, {DiffOp::Keep, 2}, {DiffOp::Add, 2, 2}}); + check_diff("abcd", "cdef", {{DiffOp::Remove, 2}, {DiffOp::Keep, 2}, {DiffOp::Add, 2}}); check_diff("mais que fais la police", "mais ou va la police", - {{DiffOp::Keep, 5}, {DiffOp::Remove, 1}, {DiffOp::Add, 1, 5}, {DiffOp::Keep, 1}, - {DiffOp::Remove, 1}, {DiffOp::Keep, 1}, {DiffOp::Add, 1, 8}, {DiffOp::Remove, 1}, + {{DiffOp::Keep, 5}, {DiffOp::Remove, 1}, {DiffOp::Add, 1}, {DiffOp::Keep, 1}, + {DiffOp::Remove, 1}, {DiffOp::Keep, 1}, {DiffOp::Add, 1}, {DiffOp::Remove, 1}, {DiffOp::Keep, 1}, {DiffOp::Remove, 2}, {DiffOp::Keep, 10}} ); check_diff("abcdefghijk", "1cdef2hij34", - {{DiffOp::Remove, 2}, {DiffOp::Add, 1, 0}, {DiffOp::Keep, 4}, {DiffOp::Remove, 1}, - {DiffOp::Add, 1, 5}, {DiffOp::Keep, 3}, {DiffOp::Add, 2, 9}, {DiffOp::Remove, 1}}); + {{DiffOp::Remove, 2}, {DiffOp::Add, 1}, {DiffOp::Keep, 4}, {DiffOp::Remove, 1}, + {DiffOp::Add, 1}, {DiffOp::Keep, 3}, {DiffOp::Add, 2}, {DiffOp::Remove, 1}}); }};