LineChangeWatcher uses Buffer::changes_since rather than listening

This commit is contained in:
Maxime Coste 2014-05-11 13:20:13 +01:00
parent a510276025
commit ddd8f8d392
5 changed files with 66 additions and 41 deletions

View File

@ -39,7 +39,7 @@ Buffer::Buffer(String name, Flags flags, std::vector<String> lines,
pos += m_lines.back().length();
}
m_changes.push_back({ Change::Insert, {0,0}, line_count() });
m_changes.push_back({ Change::Insert, {0,0}, line_count(), true });
if (flags & Flags::File)
{
@ -78,7 +78,7 @@ void Buffer::reload(std::vector<String> 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_changes.push_back({ Change::Erase, {0,0}, back_coord(), true });
m_history.clear();
m_current_undo_group.clear();
@ -99,7 +99,7 @@ void Buffer::reload(std::vector<String> lines, time_t fs_timestamp)
}
m_fs_timestamp = fs_timestamp;
m_changes.push_back({ Change::Insert, {0,0}, back_coord() });
m_changes.push_back({ Change::Insert, {0,0}, back_coord(), true });
for (auto listener : m_change_listeners)
listener->on_insert(*this, {0,0}, back_coord());
@ -459,6 +459,7 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content)
ByteCoord begin;
ByteCoord end;
bool at_end = false;
// if we inserted at the end of the buffer, we have created a new
// line without inserting a '\n'
if (is_end(pos))
@ -477,6 +478,7 @@ ByteCoord Buffer::do_insert(ByteCoord pos, const String& content)
begin = pos.column == 0 ? pos : ByteCoord{ pos.line + 1, 0 };
end = ByteCoord{ line_count()-1, m_lines.back().length() };
at_end = true;
}
else
{
@ -519,7 +521,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 });
m_changes.push_back({ Change::Insert, begin, end, at_end });
for (auto listener : m_change_listeners)
listener->on_insert(*this, begin, end);
return begin;
@ -550,7 +552,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 });
m_changes.push_back({ Change::Erase, begin, end, is_end(begin) });
for (auto listener : m_change_listeners)
listener->on_erase(*this, begin, end);
return next;

View File

@ -182,6 +182,7 @@ public:
Type type;
ByteCoord begin;
ByteCoord end;
bool at_end;
};
memoryview<Change> changes_since(size_t timestamp) const;
private:

View File

@ -1,12 +1,57 @@
#include "line_change_watcher.hh"
#include "buffer.hh"
namespace Kakoune
{
namespace
{
struct Change
{
LineCount pos;
LineCount num;
};
std::vector<Change> compute_changes(const Buffer& buffer, size_t timestamp)
{
std::vector<Change> res;
for (auto& change : buffer.changes_since(timestamp))
{
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;
}
res.push_back({begin.line, end.line - begin.line});
}
else
{
if (change.at_end and begin != ByteCoord{0,0})
{
kak_assert(begin.column == 0);
--begin.line;
}
res.push_back({begin.line, begin.line - end.line});
}
}
return res;
}
}
LineChangeWatcher::LineChangeWatcher(const Buffer& buffer)
: m_buffer(&buffer), m_timestamp(buffer.timestamp()) {}
std::vector<LineModification> LineChangeWatcher::compute_modifications()
{
std::vector<LineModification> res;
for (auto& change : m_changes)
for (auto& change : compute_changes(*m_buffer, m_timestamp))
{
auto pos = std::upper_bound(res.begin(), res.end(), change.pos,
[](const LineCount& l, const LineModification& c)
@ -58,28 +103,8 @@ std::vector<LineModification> LineChangeWatcher::compute_modifications()
it->new_line -= num_removed;
}
}
m_changes.clear();
m_timestamp = m_buffer->timestamp();
return res;
}
void LineChangeWatcher::on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end)
{
if (buffer.is_end(end))
{
kak_assert(begin.column == 0);
--begin.line;
}
m_changes.push_back({begin.line, end.line - begin.line});
}
void LineChangeWatcher::on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end)
{
if (begin.line == buffer.line_count())
{
kak_assert(begin.column == 0);
--begin.line;
}
m_changes.push_back({begin.line, begin.line - end.line});
}
}

View File

@ -1,11 +1,14 @@
#ifndef line_change_watcher_hh_INCLUDED
#define line_change_watcher_hh_INCLUDED
#include "buffer.hh"
#include "units.hh"
#include "utils.hh"
namespace Kakoune
{
class Buffer;
struct LineModification
{
LineCount old_line; // line position in the old buffer
@ -16,23 +19,17 @@ struct LineModification
LineCount diff() const { return new_line - old_line + num_added - num_removed; }
};
class LineChangeWatcher : public BufferChangeListener_AutoRegister
class LineChangeWatcher
{
public:
LineChangeWatcher (const Buffer& buffer)
: BufferChangeListener_AutoRegister(const_cast<Buffer&>(buffer)) {}
LineChangeWatcher (const Buffer& buffer);
std::vector<LineModification> compute_modifications();
private:
void on_insert(const Buffer& buffer, ByteCoord begin, ByteCoord end) override;
void on_erase(const Buffer& buffer, ByteCoord begin, ByteCoord end) override;
struct Change
{
LineCount pos;
LineCount num;
};
std::vector<Change> m_changes;
const Buffer& buffer() const { return *m_buffer; }
private:
safe_ptr<const Buffer> m_buffer;
size_t m_timestamp;
};
}

View File

@ -65,7 +65,7 @@ void WordDB::update_db()
if (modifs.empty())
return;
auto& buffer = m_change_watcher.registry();
auto& buffer = m_change_watcher.buffer();
LineToWords new_lines;
new_lines.reserve((int)buffer.line_count());