Split RegexHighlighters matches per requested buffer ranges

When a region calls the regex highlighter, it is incorrect to share
the regex cache as it means we can get matches that span multiple
regions.

Fixes #3041
This commit is contained in:
Maxime Coste 2020-01-05 18:21:20 +11:00
parent 80ffc4d34f
commit b37638dda4
5 changed files with 25 additions and 5 deletions

View File

@ -333,7 +333,8 @@ private:
size_t m_timestamp = -1; size_t m_timestamp = -1;
size_t m_regex_version = -1; size_t m_regex_version = -1;
struct RangeAndMatches { BufferRange range; MatchList matches; }; struct RangeAndMatches { BufferRange range; MatchList matches; };
Vector<RangeAndMatches, MemoryDomain::Highlight> m_matches; using RangeAndMatchesList = Vector<RangeAndMatches, MemoryDomain::Highlight>;
HashMap<BufferRange, RangeAndMatchesList, MemoryDomain::Highlight> m_matches;
}; };
BufferSideCache<Cache> m_cache; BufferSideCache<Cache> m_cache;
@ -377,17 +378,18 @@ private:
const MatchList& get_matches(const Buffer& buffer, BufferRange display_range, BufferRange buffer_range) const MatchList& get_matches(const Buffer& buffer, BufferRange display_range, BufferRange buffer_range)
{ {
Cache& cache = m_cache.get(buffer); Cache& cache = m_cache.get(buffer);
auto& matches = cache.m_matches;
if (cache.m_regex_version != m_regex_version or if (cache.m_regex_version != m_regex_version or
cache.m_timestamp != buffer.timestamp() or cache.m_timestamp != buffer.timestamp() or
matches.size() > 1000) accumulate(cache.m_matches, (size_t)0, [](size_t c, auto&& m) { return c + m.value.size(); }) > 1000)
{ {
matches.clear(); cache.m_matches.clear();
cache.m_timestamp = buffer.timestamp(); cache.m_timestamp = buffer.timestamp();
cache.m_regex_version = m_regex_version; cache.m_regex_version = m_regex_version;
} }
auto& matches = cache.m_matches[buffer_range];
const LineCount line_offset = 3; const LineCount line_offset = 3;
BufferRange range{std::max<BufferCoord>(buffer_range.begin, display_range.begin.line - line_offset), BufferRange range{std::max<BufferCoord>(buffer_range.begin, display_range.begin.line - line_offset),
std::min<BufferCoord>(buffer_range.end, display_range.end.line + line_offset)}; std::min<BufferCoord>(buffer_range.end, display_range.end.line + line_offset)};
@ -1833,7 +1835,7 @@ public:
const bool apply_default = default_region_it != m_regions.end(); const bool apply_default = default_region_it != m_regions.end();
auto last_begin = (begin == regions.begin()) ? auto last_begin = (begin == regions.begin()) ?
BufferCoord{0,0} : (begin-1)->end; range.begin : (begin-1)->end;
kak_assert(begin <= end); kak_assert(begin <= end);
for (; begin != end; ++begin) for (; begin != end; ++begin)
{ {

View File

@ -0,0 +1,6 @@
- _foo
- bar_
- _baz_
_foo
bar_

View File

@ -0,0 +1,5 @@
add-highlighter shared/test regions
add-highlighter shared/test/base default-region regions
add-highlighter shared/test/base/base default-region regex _[^_]+_ 0:+b
add-highlighter shared/test/item region '^- \K' $ ref test/base
add-highlighter window/ ref test

View File

@ -0,0 +1,7 @@
ui_out '{ "jsonrpc": "2.0", "method": "set_ui_options", "params": [{}] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "-" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " _foo\u000a" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "- bar_\u000a" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "- " }, { "face": { "fg": "default", "bg": "default", "attributes": ["bold"] }, "contents": "_baz_" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "\u000a" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "\u000a" }], [{ "face": { "fg": "default", "bg": "default", "attributes": ["bold"] }, "contents": "_foo\u000a" }], [{ "face": { "fg": "default", "bg": "default", "attributes": ["bold"] }, "contents": "bar_" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }'
ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] }'
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'