Use a per line caching strategy for region highlighter
This commit is contained in:
parent
b247a05e43
commit
d466193ee7
|
@ -45,7 +45,7 @@ addhl -def-group cpp regex "\<(void|int|char|unsigned|float|bool|size_t)\>" 0:ty
|
||||||
addhl -def-group cpp regex "\<(while|for|if|else|do|switch|case|default|goto|break|continue|return|using|try|catch|throw|new|delete|and|or|not|operator|explicit)\>" 0:keyword
|
addhl -def-group cpp regex "\<(while|for|if|else|do|switch|case|default|goto|break|continue|return|using|try|catch|throw|new|delete|and|or|not|operator|explicit)\>" 0:keyword
|
||||||
addhl -def-group cpp regex "\<(const|mutable|auto|namespace|inline|static|volatile|class|struct|enum|union|public|protected|private|template|typedef|virtual|friend|extern|typename|override|final)\>" 0:attribute
|
addhl -def-group cpp regex "\<(const|mutable|auto|namespace|inline|static|volatile|class|struct|enum|union|public|protected|private|template|typedef|virtual|friend|extern|typename|override|final)\>" 0:attribute
|
||||||
addhl -def-group cpp regex "^\h*?#.*?(?<!\\)$" 0:macro
|
addhl -def-group cpp regex "^\h*?#.*?(?<!\\)$" 0:macro
|
||||||
addhl -def-group cpp region %{(?<!')"} %{(\`|[^\\])(\\\\)*"} string
|
addhl -def-group cpp region %{(?<!')"} %{(?<!\\)(\\\\)*"} string
|
||||||
addhl -def-group cpp region /\* \*/ comment
|
addhl -def-group cpp region /\* \*/ comment
|
||||||
addhl -def-group cpp regex "(//[^\n]*\n)" 0:comment
|
addhl -def-group cpp regex "(//[^\n]*\n)" 0:comment
|
||||||
|
|
||||||
|
|
|
@ -524,47 +524,100 @@ public:
|
||||||
|
|
||||||
void operator()(const Context& context, DisplayBuffer& display_buffer)
|
void operator()(const Context& context, DisplayBuffer& display_buffer)
|
||||||
{
|
{
|
||||||
auto& cache = update_cache_ifn(context.buffer());
|
auto& regions = update_cache_ifn(context.buffer());
|
||||||
for (auto& pair : cache.regions)
|
for (auto& region : regions)
|
||||||
m_func(context, display_buffer, pair.first, pair.second);
|
m_func(context, display_buffer, region.begin, region.end);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Regex m_begin;
|
Regex m_begin;
|
||||||
Regex m_end;
|
Regex m_end;
|
||||||
HighlightFunc m_func;
|
HighlightFunc m_func;
|
||||||
|
|
||||||
|
struct Region
|
||||||
|
{
|
||||||
|
BufferCoord begin;
|
||||||
|
BufferCoord end;
|
||||||
|
};
|
||||||
|
using RegionList = std::vector<Region>;
|
||||||
|
|
||||||
|
struct Match
|
||||||
|
{
|
||||||
|
size_t timestamp;
|
||||||
|
BufferCoord begin;
|
||||||
|
BufferCoord end;
|
||||||
|
};
|
||||||
|
using MatchList = std::vector<Match>;
|
||||||
|
|
||||||
struct RegionCache
|
struct RegionCache
|
||||||
{
|
{
|
||||||
size_t timestamp = -1;
|
size_t timestamp = 0;
|
||||||
std::vector<std::pair<BufferCoord, BufferCoord>> regions;
|
MatchList begin_matches;
|
||||||
|
MatchList end_matches;
|
||||||
|
RegionList regions;
|
||||||
};
|
};
|
||||||
BufferSideCache<RegionCache> m_cache;
|
BufferSideCache<RegionCache> m_cache;
|
||||||
|
|
||||||
RegionCache& update_cache_ifn(const Buffer& buffer)
|
const RegionList& update_cache_ifn(const Buffer& buffer)
|
||||||
{
|
{
|
||||||
RegionCache& cache = m_cache.get(buffer);
|
RegionCache& cache = m_cache.get(buffer);
|
||||||
|
const size_t buf_timestamp = buffer.timestamp();
|
||||||
|
if (cache.timestamp == buf_timestamp)
|
||||||
|
return cache.regions;
|
||||||
|
|
||||||
if (cache.timestamp == buffer.timestamp())
|
update_matches(buffer, cache.timestamp, cache.begin_matches, m_begin);
|
||||||
return cache;
|
update_matches(buffer, cache.timestamp, cache.end_matches, m_end);
|
||||||
|
|
||||||
cache.regions.clear();
|
cache.regions.clear();
|
||||||
|
for (auto beg_it = cache.begin_matches.begin(), end_it = cache.end_matches.begin();
|
||||||
boost::match_results<BufferIterator> results;
|
beg_it != cache.begin_matches.end(); )
|
||||||
auto pos = buffer.begin();
|
|
||||||
auto end = buffer.end();
|
|
||||||
while (boost::regex_search(pos, end, results, m_begin))
|
|
||||||
{
|
{
|
||||||
pos = results[0].first;
|
auto compare_matches = [&](const Match& lhs, const Match& rhs) {
|
||||||
if (boost::regex_search(results[0].second, end, results, m_end))
|
return lhs.end < rhs.end;
|
||||||
|
};
|
||||||
|
end_it = std::upper_bound(end_it, cache.end_matches.end(),
|
||||||
|
*beg_it, compare_matches);
|
||||||
|
if (end_it == cache.end_matches.end())
|
||||||
{
|
{
|
||||||
cache.regions.emplace_back(pos.coord(), results[0].second.coord());
|
cache.regions.push_back({beg_it->begin, buffer.end_coord()});
|
||||||
pos = results[0].second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cache.regions.push_back({beg_it->begin, end_it->end});
|
||||||
|
beg_it = std::upper_bound(beg_it, cache.begin_matches.end(),
|
||||||
|
*end_it, compare_matches);
|
||||||
|
}
|
||||||
|
}
|
||||||
cache.timestamp = buffer.timestamp();
|
cache.timestamp = buffer.timestamp();
|
||||||
return cache;
|
return cache.regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_matches(const Buffer& buffer, size_t timestamp, MatchList& matches, const Regex& regex)
|
||||||
|
{
|
||||||
|
const size_t buf_timestamp = buffer.timestamp();
|
||||||
|
// remove out of date matches
|
||||||
|
for (auto it = matches.begin(); it != matches.end();)
|
||||||
|
{
|
||||||
|
if (it->timestamp < buffer.line_timestamp(it->begin.line))
|
||||||
|
it = matches.erase(it);
|
||||||
|
else ++it;
|
||||||
|
}
|
||||||
|
// try to find new matches in each updated lines
|
||||||
|
for (auto line = 0_line; line < buffer.line_count(); ++line)
|
||||||
|
{
|
||||||
|
if (buffer.line_timestamp(line) > timestamp)
|
||||||
|
{
|
||||||
|
auto& l = buffer[line];
|
||||||
|
for (boost::regex_iterator<String::const_iterator> it{l.begin(), l.end(), regex}, end{}; it != end; ++it)
|
||||||
|
{
|
||||||
|
BufferCoord b{line, (int)((*it)[0].first - l.begin())};
|
||||||
|
BufferCoord e{line, (int)((*it)[0].second - l.begin())};
|
||||||
|
matches.push_back({ buf_timestamp, b, e });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(matches.begin(), matches.end(),
|
||||||
|
[](const Match& lhs, const Match& rhs) { return lhs.begin < rhs.begin; });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user