From b37638dda4531efd5953ec12a0331bcb0876ada3 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 5 Jan 2020 18:21:20 +1100 Subject: [PATCH] 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 --- src/highlighters.cc | 12 +++++++----- .../3041-invalid-regex-highlight-accross-regions/cmd | 0 .../3041-invalid-regex-highlight-accross-regions/in | 6 ++++++ .../3041-invalid-regex-highlight-accross-regions/rc | 5 +++++ .../script | 7 +++++++ 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 test/regression/3041-invalid-regex-highlight-accross-regions/cmd create mode 100644 test/regression/3041-invalid-regex-highlight-accross-regions/in create mode 100644 test/regression/3041-invalid-regex-highlight-accross-regions/rc create mode 100644 test/regression/3041-invalid-regex-highlight-accross-regions/script diff --git a/src/highlighters.cc b/src/highlighters.cc index 8878a726..82acdd53 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -333,7 +333,8 @@ private: size_t m_timestamp = -1; size_t m_regex_version = -1; struct RangeAndMatches { BufferRange range; MatchList matches; }; - Vector m_matches; + using RangeAndMatchesList = Vector; + HashMap m_matches; }; BufferSideCache m_cache; @@ -377,17 +378,18 @@ private: const MatchList& get_matches(const Buffer& buffer, BufferRange display_range, BufferRange buffer_range) { Cache& cache = m_cache.get(buffer); - auto& matches = cache.m_matches; if (cache.m_regex_version != m_regex_version 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_regex_version = m_regex_version; } + auto& matches = cache.m_matches[buffer_range]; + const LineCount line_offset = 3; BufferRange range{std::max(buffer_range.begin, display_range.begin.line - line_offset), std::min(buffer_range.end, display_range.end.line + line_offset)}; @@ -1833,7 +1835,7 @@ public: const bool apply_default = default_region_it != m_regions.end(); auto last_begin = (begin == regions.begin()) ? - BufferCoord{0,0} : (begin-1)->end; + range.begin : (begin-1)->end; kak_assert(begin <= end); for (; begin != end; ++begin) { diff --git a/test/regression/3041-invalid-regex-highlight-accross-regions/cmd b/test/regression/3041-invalid-regex-highlight-accross-regions/cmd new file mode 100644 index 00000000..e69de29b diff --git a/test/regression/3041-invalid-regex-highlight-accross-regions/in b/test/regression/3041-invalid-regex-highlight-accross-regions/in new file mode 100644 index 00000000..fbcb3f05 --- /dev/null +++ b/test/regression/3041-invalid-regex-highlight-accross-regions/in @@ -0,0 +1,6 @@ +- _foo +- bar_ +- _baz_ + +_foo +bar_ diff --git a/test/regression/3041-invalid-regex-highlight-accross-regions/rc b/test/regression/3041-invalid-regex-highlight-accross-regions/rc new file mode 100644 index 00000000..888e7f6f --- /dev/null +++ b/test/regression/3041-invalid-regex-highlight-accross-regions/rc @@ -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 diff --git a/test/regression/3041-invalid-regex-highlight-accross-regions/script b/test/regression/3041-invalid-regex-highlight-accross-regions/script new file mode 100644 index 00000000..9a2016c8 --- /dev/null +++ b/test/regression/3041-invalid-regex-highlight-accross-regions/script @@ -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] }'