RegionHighlighter: Find the lines to be reparsed using the changes

This commit is contained in:
Maxime Coste 2014-01-15 20:28:58 +00:00
parent c2f18e6e78
commit a6b386e9b8

View File

@ -592,6 +592,48 @@ private:
};
BufferSideCache<Cache> m_cache;
static std::vector<LineCount> compute_lines_to_update(const std::vector<LineChange>& changes)
{
std::vector<LineCount> res;
for (auto& change : changes)
{
if (change.num == 0)
res.push_back(change.pos);
else if (change.num > 0)
{
for (auto& l : res)
{
if (l > change.pos)
l += change.num;
}
for (LineCount i = 0; i <= change.num; ++i)
res.push_back(change.pos + i);
}
else
{
for (auto it = res.begin(); it != res.end(); )
{
auto& line = *it;
if (line > change.pos)
{
line += change.num;
if (line < change.pos)
{
std::swap(line, res.back());
res.pop_back();
continue;
}
}
++it;
}
res.push_back(change.pos);
}
}
std::sort(res.begin(), res.end());
res.erase(std::unique(res.begin(), res.end()), res.end());
return res;
}
const RegionList& update_cache_ifn(const Buffer& buffer)
{
Cache& cache = m_cache.get(buffer);
@ -599,14 +641,23 @@ private:
if (cache.timestamp == buf_timestamp)
return cache.regions;
std::sort(cache.changes.begin(), cache.changes.end(),
[](const LineChange& lhs, const LineChange& rhs)
{ return lhs.pos < rhs.pos; });
for (size_t i = 1; i < cache.changes.size(); ++i)
cache.changes[i].num += cache.changes[i-1].num;
update_matches(buffer, cache, cache.begin_matches, m_begin);
update_matches(buffer, cache, cache.end_matches, m_end);
cache.changes.clear();
if (cache.timestamp == 0)
{
find_matches(buffer, cache.begin_matches, m_begin);
find_matches(buffer, cache.end_matches, m_end);
}
else
{
auto to_update = compute_lines_to_update(cache.changes);
std::sort(cache.changes.begin(), cache.changes.end(),
[](const LineChange& lhs, const LineChange& rhs)
{ return lhs.pos < rhs.pos; });
for (size_t i = 1; i < cache.changes.size(); ++i)
cache.changes[i].num += cache.changes[i-1].num;
update_matches(buffer, cache, to_update, cache.begin_matches, m_begin);
update_matches(buffer, cache, to_update, cache.end_matches, m_end);
cache.changes.clear();
}
cache.regions.clear();
for (auto beg_it = cache.begin_matches.begin(), end_it = cache.end_matches.begin();
@ -629,7 +680,22 @@ private:
return cache.regions;
}
void update_matches(const Buffer& buffer, const Cache& cache, MatchList& matches, const Regex& regex)
void find_matches(const Buffer& buffer, MatchList& matches, const Regex& regex)
{
const size_t buf_timestamp = buffer.timestamp();
for (auto line = 0_line, end = buffer.line_count(); line < end; ++line)
{
auto& l = buffer[line];
for (boost::regex_iterator<String::const_iterator> it{l.begin(), l.end(), regex}, end{}; it != end; ++it)
{
ByteCount b = (int)((*it)[0].first - l.begin());
ByteCount e = (int)((*it)[0].second - l.begin());
matches.push_back({ buf_timestamp, line, b, e });
}
}
}
void update_matches(const Buffer& buffer, const Cache& cache, memoryview<LineCount> to_update, MatchList& matches, const Regex& regex)
{
const size_t buf_timestamp = buffer.timestamp();
// remove out of date matches and update line for others
@ -663,17 +729,15 @@ private:
size_t pivot = matches.size();
// try to find new matches in each updated lines
for (auto line = 0_line, end = buffer.line_count(); line < end; ++line)
for (auto line : to_update)
{
if (buffer.line_timestamp(line) > cache.timestamp)
kak_assert(buffer.line_timestamp(line) > cache.timestamp);
auto& l = buffer[line];
for (boost::regex_iterator<String::const_iterator> it{l.begin(), l.end(), regex}, end{}; it != end; ++it)
{
auto& l = buffer[line];
for (boost::regex_iterator<String::const_iterator> it{l.begin(), l.end(), regex}, end{}; it != end; ++it)
{
ByteCount b = (int)((*it)[0].first - l.begin());
ByteCount e = (int)((*it)[0].second - l.begin());
matches.push_back({ buf_timestamp, line, b, e });
}
ByteCount b = (int)((*it)[0].first - l.begin());
ByteCount e = (int)((*it)[0].second - l.begin());
matches.push_back({ buf_timestamp, line, b, e });
}
}
std::inplace_merge(matches.begin(), matches.begin() + pivot, matches.end(),