diff options
Diffstat (limited to 'src/line_modification.cc')
| -rw-r--r-- | src/line_modification.cc | 109 |
1 files changed, 46 insertions, 63 deletions
diff --git a/src/line_modification.cc b/src/line_modification.cc index 96249856..1943350f 100644 --- a/src/line_modification.cc +++ b/src/line_modification.cc @@ -5,41 +5,33 @@ namespace Kakoune { -namespace +static LineModification make_line_modif(const Buffer::Change& change) { - -struct LineChange -{ - LineChange(const Buffer::Change& change) + LineModification res = {}; + res.old_line = change.begin.line; + res.new_line = change.begin.line; + if (change.type == Buffer::Change::Insert) { - ByteCoord begin = change.begin; - ByteCoord end = change.end; - if (change.type == Buffer::Change::Insert) - { - if (change.at_end and begin != ByteCoord{0,0}) - { - kak_assert(begin.column == 0); - --begin.line; - } - pos = begin.line; - num = end.line - begin.line; - } - else - { - if (change.at_end and begin != ByteCoord{0,0}) - { - kak_assert(begin.column == 0); - --begin.line; - } - pos = begin.line; - num = begin.line - end.line; - } + res.num_added = change.end.line - change.begin.line; + // inserted a new line at buffer end but end coord is on same line + if (change.at_end and change.end.column != 0) + ++res.num_added; } - - LineCount pos; - LineCount num; -}; - + else + { + res.num_removed = change.end.line - change.begin.line; + // removed last line, but end coord is on same line + if (change.at_end and change.end.column != 0) + ++res.num_removed; + } + // modified a line + if (not change.at_end and + (change.begin.column != 0 or change.end.column != 0)) + { + ++res.num_removed; + ++res.num_added; + } + return res; } Vector<LineModification> compute_line_modifications(const Buffer& buffer, size_t timestamp) @@ -47,60 +39,51 @@ Vector<LineModification> compute_line_modifications(const Buffer& buffer, size_t Vector<LineModification> res; for (auto& buf_change : buffer.changes_since(timestamp)) { - const LineChange change(buf_change); + auto change = make_line_modif(buf_change); - auto pos = std::upper_bound(res.begin(), res.end(), change.pos, + auto pos = std::upper_bound(res.begin(), res.end(), change.new_line, [](const LineCount& l, const LineModification& c) { return l < c.new_line; }); if (pos != res.begin()) { auto& prev = *(pos-1); - if (change.pos <= prev.new_line + prev.num_added) + if (change.new_line <= prev.new_line + prev.num_added) + { --pos; + LineCount removed_from_previously_added_by_pos = clamp(pos->new_line + pos->num_added - change.new_line, 0_line, std::min(pos->num_added, change.num_removed)); + pos->num_removed += change.num_removed - removed_from_previously_added_by_pos; + pos->num_added += change.num_added - removed_from_previously_added_by_pos; + } else - pos = res.insert(pos, {change.pos - prev.diff(), change.pos, 0, 0}); + { + change.old_line -= prev.diff(); + pos = res.insert(pos, change); + } } else - pos = res.insert(pos, {change.pos, change.pos, 0, 0}); + pos = res.insert(pos, change); auto& modif = *pos; auto next = pos + 1; - if (change.num > 0) + if (buf_change.type == Buffer::Change::Erase) { - modif.num_added += change.num; - for (auto it = next; it != res.end(); ++it) - it->new_line += change.num; - } - if (change.num < 0) - { - const LineCount num_removed = -change.num; - - auto delend = std::upper_bound(next, res.end(), change.pos + num_removed, + auto delend = std::upper_bound(next, res.end(), change.new_line + change.num_removed, [](const LineCount& l, const LineModification& c) { return l < c.new_line; }); for (auto it = next; it != delend; ++it) { - LineCount removed_from_it = (change.pos + num_removed - it->new_line); - modif.num_removed += it->num_removed - std::min(removed_from_it, it->num_added); - modif.num_added += std::max(0_line, it->num_added - removed_from_it); + LineCount removed_from_previously_added_by_it = std::min(it->num_added, change.new_line + change.num_removed - it->new_line); + modif.num_removed += it->num_removed - removed_from_previously_added_by_it; + modif.num_added += it->num_added - removed_from_previously_added_by_it; } next = res.erase(next, delend); - - const LineCount num_added_after_pos = - modif.new_line + modif.num_added - change.pos; - const LineCount num_removed_from_added = - std::min(num_removed, num_added_after_pos); - - kak_assert(modif.num_added >= num_removed_from_added); - - modif.num_added -= num_removed_from_added; - modif.num_removed += num_removed - num_removed_from_added; - - for (auto it = next; it != res.end(); ++it) - it->new_line -= num_removed; } + + auto diff = buf_change.end.line - buf_change.begin.line; + for (auto it = next; it != res.end(); ++it) + it->new_line += diff; } return res; } |
