#ifndef changes_hh_INCLUDED #define changes_hh_INCLUDED #include "buffer.hh" #include "coord.hh" namespace Kakoune { // This tracks position changes for changes that are done // in a forward way (each change takes place at a position) // *after* the previous one. struct ForwardChangesTracker { BufferCoord cur_pos; // last change position at current modification BufferCoord old_pos; // last change position at start void update(const Buffer::Change& change); void update(const Buffer& buffer, size_t& timestamp); BufferCoord get_old_coord(BufferCoord coord) const; BufferCoord get_new_coord(BufferCoord coord) const; BufferCoord get_new_coord_tolerant(BufferCoord coord) const; bool relevant(const Buffer::Change& change, BufferCoord old_coord) const; }; const Buffer::Change* forward_sorted_until(const Buffer::Change* first, const Buffer::Change* last); const Buffer::Change* backward_sorted_until(const Buffer::Change* first, const Buffer::Change* last); template void update_forward(ConstArrayView changes, RangeContainer& ranges) { ForwardChangesTracker changes_tracker; auto advance_while_relevant = [&, it = changes.begin()] (const BufferCoord& pos) mutable { while (it != changes.end() and changes_tracker.relevant(*it, pos)) changes_tracker.update(*it++); }; for (auto& range : ranges) { auto& first = get_first(range); auto& last = get_last(range); advance_while_relevant(first); first = changes_tracker.get_new_coord_tolerant(first); advance_while_relevant(last); last = changes_tracker.get_new_coord_tolerant(last); } } template void update_backward(ConstArrayView changes, RangeContainer& ranges) { ForwardChangesTracker changes_tracker; auto advance_while_relevant = [&, it = changes.rbegin()] (const BufferCoord& pos) mutable { while (it != changes.rend()) { const Buffer::Change change{it->type, changes_tracker.get_new_coord(it->begin), changes_tracker.get_new_coord(it->end)}; if (not changes_tracker.relevant(change, pos)) break; changes_tracker.update(change); ++it; } }; for (auto& range : ranges) { auto& first = get_first(range); auto& last = get_last(range); advance_while_relevant(first); first = changes_tracker.get_new_coord_tolerant(first); advance_while_relevant(last); last = changes_tracker.get_new_coord_tolerant(last); } } } #endif // changes_hh_INCLUDED