From a51027602544bb7d67a3313cca859bac897894b6 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 11 May 2014 12:20:59 +0100 Subject: [PATCH] Maintain an append-only list of changes in Buffer --- src/buffer.cc | 34 +++++++++++++++++----------------- src/buffer.hh | 12 +++++++++++- src/buffer.inl.hh | 8 +++++++- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index dbdd6247..5219f1b6 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -19,8 +19,6 @@ Buffer::Buffer(String name, Flags flags, std::vector lines, m_flags(flags | Flags::NoUndo), m_history(), m_history_cursor(m_history.begin()), m_last_save_undo_index(0), - // start buffer timestamp at 1 so that caches can init to 0 - m_timestamp(1), m_fs_timestamp(fs_timestamp), m_hooks(GlobalHooks::instance()), m_options(GlobalOptions::instance()), @@ -37,10 +35,12 @@ Buffer::Buffer(String name, Flags flags, std::vector lines, for (auto& line : lines) { kak_assert(not line.empty() and line.back() == '\n'); - m_lines.emplace_back(Line{ m_timestamp, pos, std::move(line) }); + m_lines.emplace_back(Line{ m_changes.size()+1, pos, std::move(line) }); pos += m_lines.back().length(); } + m_changes.push_back({ Change::Insert, {0,0}, line_count() }); + if (flags & Flags::File) { if (flags & Flags::New) @@ -78,12 +78,13 @@ void Buffer::reload(std::vector lines, time_t fs_timestamp) for (auto listener : m_change_listeners) listener->on_erase(*this, {0,0}, back_coord()); + m_changes.push_back({ Change::Erase, {0,0}, back_coord() }); + m_history.clear(); m_current_undo_group.clear(); m_history_cursor = m_history.begin(); m_last_save_undo_index = 0; m_lines.clear(); - ++m_timestamp; if (lines.empty()) lines.emplace_back("\n"); @@ -93,11 +94,13 @@ void Buffer::reload(std::vector lines, time_t fs_timestamp) for (auto& line : lines) { kak_assert(not line.empty() and line.back() == '\n'); - m_lines.emplace_back(Line{ m_timestamp, pos, std::move(line) }); + m_lines.emplace_back(Line{ m_changes.size()+1, pos, std::move(line) }); pos += m_lines.back().length(); } m_fs_timestamp = fs_timestamp; + m_changes.push_back({ Change::Insert, {0,0}, back_coord() }); + for (auto listener : m_change_listeners) listener->on_insert(*this, {0,0}, back_coord()); } @@ -448,7 +451,6 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content) if (content.empty()) return pos; - ++m_timestamp; ByteCount offset = this->offset(pos); // all following lines advanced by length @@ -466,12 +468,12 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content) { if (content[i] == '\n') { - m_lines.push_back({ m_timestamp, offset + start, content.substr(start, i + 1 - start) }); + m_lines.push_back({ m_changes.size()+1, offset + start, content.substr(start, i + 1 - start) }); start = i + 1; } } if (start != content.length()) - m_lines.push_back({ m_timestamp, offset + start, content.substr(start) }); + m_lines.push_back({ m_changes.size()+1, offset + start, content.substr(start) }); begin = pos.column == 0 ? pos : ByteCoord{ pos.line + 1, 0 }; end = ByteCoord{ line_count()-1, m_lines.back().length() }; @@ -492,18 +494,18 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content) if (start == 0) { line_content = prefix + line_content; - new_lines.push_back({ m_timestamp, offset + start - prefix.length(), + new_lines.push_back({ m_changes.size()+1, offset + start - prefix.length(), std::move(line_content) }); } else - new_lines.push_back({ m_timestamp, offset + start, std::move(line_content) }); + new_lines.push_back({ m_changes.size()+1, offset + start, std::move(line_content) }); start = i + 1; } } if (start == 0) - new_lines.push_back({ m_timestamp, offset + start - prefix.length(), prefix + content + suffix }); + new_lines.push_back({ m_changes.size()+1, offset + start - prefix.length(), prefix + content + suffix }); else if (start != content.length() or not suffix.empty()) - new_lines.push_back({ m_timestamp, offset + start, content.substr(start) + suffix }); + new_lines.push_back({ m_changes.size()+1, offset + start, content.substr(start) + suffix }); LineCount last_line = pos.line + new_lines.size() - 1; @@ -517,6 +519,7 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content) end = ByteCoord{ last_line, m_lines[last_line].length() - suffix.length() }; } + m_changes.push_back({ Change::Insert, begin, end }); for (auto listener : m_change_listeners) listener->on_insert(*this, begin, end); return begin; @@ -526,11 +529,10 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end) { kak_assert(is_valid(begin)); kak_assert(is_valid(end)); - ++m_timestamp; const ByteCount length = distance(begin, end); String prefix = m_lines[begin.line].content.substr(0, begin.column); String suffix = m_lines[end.line].content.substr(end.column); - Line new_line = { m_timestamp, m_lines[begin.line].start, prefix + suffix }; + Line new_line = { m_changes.size()+1, m_lines[begin.line].start, prefix + suffix }; ByteCoord next; if (new_line.length() != 0) @@ -548,6 +550,7 @@ ByteCoord Buffer::do_erase(ByteCoord begin, ByteCoord end) for (LineCount i = begin.line+1; i < line_count(); ++i) m_lines[i].start -= length; + m_changes.push_back({ Change::Erase, begin, end }); for (auto listener : m_change_listeners) listener->on_erase(*this, begin, end); return next; @@ -628,10 +631,7 @@ void Buffer::notify_saved() m_flags &= ~Flags::New; size_t history_cursor_index = m_history_cursor - m_history.begin(); if (m_last_save_undo_index != history_cursor_index) - { - ++m_timestamp; m_last_save_undo_index = history_cursor_index; - } m_fs_timestamp = get_fs_timestamp(m_name); } diff --git a/src/buffer.hh b/src/buffer.hh index ff09528e..46b982a8 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -175,6 +175,15 @@ public: void reload(std::vector lines, time_t fs_timestamp = InvalidTime); void check_invariant() const; + + struct Change + { + enum Type { Insert, Erase }; + Type type; + ByteCoord begin; + ByteCoord end; + }; + memoryview changes_since(size_t timestamp) const; private: void on_option_changed(const Option& option) override; @@ -215,7 +224,8 @@ private: void revert_modification(const Modification& modification); size_t m_last_save_undo_index; - size_t m_timestamp; + + std::vector m_changes; time_t m_fs_timestamp; diff --git a/src/buffer.inl.hh b/src/buffer.inl.hh index 1920857d..9cfa2d0f 100644 --- a/src/buffer.inl.hh +++ b/src/buffer.inl.hh @@ -88,7 +88,13 @@ inline LineCount Buffer::line_count() const inline size_t Buffer::timestamp() const { - return m_timestamp; + return m_changes.size(); +} + +inline memoryview Buffer::changes_since(size_t timestamp) const +{ + return { m_changes.data() + timestamp, + m_changes.data() + m_changes.size() }; } inline size_t Buffer::line_timestamp(LineCount line) const