Remove region highlighter, rename multi_regions to regions, cleanup

This commit is contained in:
Maxime Coste 2014-07-14 21:42:19 +01:00
parent ec37adc523
commit ac5cbba0ae
11 changed files with 58 additions and 178 deletions

View File

@ -39,7 +39,7 @@ def -hidden _cpp_indent_on_closing_curly_brace %[
try %[ exec -draft "hm<space><a-?>(class|struct)<ret><a-k>\`(class|struct)[^{}\n]+(\n)?\s*\{\'<ret><a-space>ma;<esc>" ] try %[ exec -draft "hm<space><a-?>(class|struct)<ret><a-k>\`(class|struct)[^{}\n]+(\n)?\s*\{\'<ret><a-space>ma;<esc>" ]
] ]
addhl -group / multi_region -default code cpp \ addhl -group / regions -default code cpp \
string %{(?<!')"} %{(?<!\\)(\\\\)*"} '' \ string %{(?<!')"} %{(?<!\\)(\\\\)*"} '' \
comment /\* \*/ '' \ comment /\* \*/ '' \
comment // $ '' \ comment // $ '' \

View File

@ -15,10 +15,10 @@ hook global BufCreate .*[.](fish) %{
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code fish \ addhl -group / regions -default code fish \
double_string '"' (?<!\\)(\\\\)*" '' \ double_string '"' (?<!\\)(\\\\)*" '' \
single_string "'" "'" '' \ single_string "'" "'" '' \
comment '#' '$' '' comment '#' '$' ''
addhl -group /fish/double_string fill string addhl -group /fish/double_string fill string
addhl -group /fish/double_string regex (\$\w+)|(\{\$\w+\}) 0:identifier addhl -group /fish/double_string regex (\$\w+)|(\{\$\w+\}) 0:identifier

View File

@ -12,12 +12,12 @@ hook global BufCreate .*[.](js) %{
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code javascript \ addhl -group / regions -default code javascript \
double_string '"' (?<!\\)(\\\\)*" '' \ double_string '"' (?<!\\)(\\\\)*" '' \
single_string "'" "'" '' \ single_string "'" "'" '' \
comment // '$' '' \ comment // '$' '' \
comment /[*] [*]/ '' \ comment /[*] [*]/ '' \
regex / (?<!\\)(\\\\)*/[gimy]* '' regex / (?<!\\)(\\\\)*/[gimy]* ''
# Regular expression flags are: g → global match, i → ignore case, m → multi-lines, y → sticky # Regular expression flags are: g → global match, i → ignore case, m → multi-lines, y → sticky
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

View File

@ -15,7 +15,7 @@ hook global BufCreate .*[.](json) %{
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code json \ addhl -group / regions -default code json \
string '"' (?<!\\)(\\\\)*" '' string '"' (?<!\\)(\\\\)*" ''
addhl -group /json/string fill string addhl -group /json/string fill string

View File

@ -2,7 +2,7 @@ hook global BufCreate (.*/)?(kakrc|.*.kak) %{
set buffer filetype kak set buffer filetype kak
} }
addhl -group / multi_region -default code kakrc \ addhl -group / regions -default code kakrc \
comment (^|\h)\K\# $ '' \ comment (^|\h)\K\# $ '' \
double_string %{(^|\h)"} %{(?<!\\)(\\\\)*"} '' \ double_string %{(^|\h)"} %{(?<!\\)(\\\\)*"} '' \
single_string %{(^|\h)'} %{(?<!\\)(\\\\)*'} '' \ single_string %{(^|\h)'} %{(?<!\\)(\\\\)*'} '' \

View File

@ -15,12 +15,12 @@ hook global BufCreate .*[.](py) %{
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code python \ addhl -group / regions -default code python \
double_string '"""' '"""' '' \ double_string '"""' '"""' '' \
single_string "'''" "'''" '' \ single_string "'''" "'''" '' \
double_string '"' (?<!\\)(\\\\)*" '' \ double_string '"' (?<!\\)(\\\\)*" '' \
single_string "'" "'" '' \ single_string "'" "'" '' \
comment '#' '$' '' comment '#' '$' ''
addhl -group /python/double_string fill string addhl -group /python/double_string fill string
addhl -group /python/single_string fill string addhl -group /python/single_string fill string

View File

@ -15,7 +15,7 @@ hook global BufCreate .*(([.](rb))|(irbrc)|(pryrc)|(Capfile|[.]cap)|(Gemfile)|(G
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code ruby \ addhl -group / regions -default code ruby \
double_string '"' (?<!\\)(\\\\)*" '' \ double_string '"' (?<!\\)(\\\\)*" '' \
single_string "'" "'" '' \ single_string "'" "'" '' \
backtick '`' (?<!\\)(\\\\)*` '' \ backtick '`' (?<!\\)(\\\\)*` '' \
@ -31,16 +31,21 @@ addhl -group / multi_region -default code ruby \
# Literals are: i → array of symbols, q → string, r → regular expression, s → symbol, w → array of words, x → capture shell result # Literals are: i → array of symbols, q → string, r → regular expression, s → symbol, w → array of words, x → capture shell result
addhl -group /ruby/double_string fill string addhl -group /ruby/double_string fill string
addhl -group /ruby/double_string region interpolation \Q#{ \} \{ addhl -group /ruby/double_string regions regions interpolation \Q#{ \} \{
addhl -group /ruby/double_string/interpolation/content fill meta addhl -group /ruby/double_string/regions/interpolation fill meta
addhl -group /ruby/single_string fill string addhl -group /ruby/single_string fill string
addhl -group /ruby/backtick fill meta addhl -group /ruby/backtick fill meta
addhl -group /ruby/backtick region interpolation \Q#{ \} \{ addhl -group /ruby/backtick regions regions interpolation \Q#{ \} \{
addhl -group /ruby/backtick/interpolation/content fill meta addhl -group /ruby/backtick/regions/interpolation fill meta
addhl -group /ruby/regex fill meta addhl -group /ruby/regex fill meta
addhl -group /ruby/regex region interpolation \Q#{ \} \{ addhl -group /ruby/regex regions regions interpolation \Q#{ \} \{
addhl -group /ruby/regex/interpolation/content fill meta addhl -group /ruby/regex/regions/interpolation fill meta
addhl -group /ruby/comment fill comment addhl -group /ruby/comment fill comment
addhl -group /ruby/literal fill meta addhl -group /ruby/literal fill meta
addhl -group /ruby/code regex \<([a-z]\w+:)|([$@][a-z]\w+)|(\W\K:[a-z]\w+[=?!]?) 0:identifier addhl -group /ruby/code regex \<([a-z]\w+:)|([$@][a-z]\w+)|(\W\K:[a-z]\w+[=?!]?) 0:identifier

View File

@ -6,7 +6,7 @@ hook global BufSetOption mimetype=text/x-shellscript %{
set buffer filetype sh set buffer filetype sh
} }
addhl -group / multi_region -default code sh \ addhl -group / regions -default code sh \
double_string %{(^|\h)"} %{(?<!\\)(\\\\)*"} '' \ double_string %{(^|\h)"} %{(?<!\\)(\\\\)*"} '' \
single_string %{(^|\h)'} %{(?<!\\)(\\\\)*'} '' \ single_string %{(^|\h)'} %{(?<!\\)(\\\\)*'} '' \
comment '#' '$' '' comment '#' '$' ''

View File

@ -15,7 +15,7 @@ hook global BufCreate .*[.](yaml) %{
# Highlighters # Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾ # ‾‾‾‾‾‾‾‾‾‾‾‾
addhl -group / multi_region -default code yaml \ addhl -group / regions -default code yaml \
double_string '"' (?<!\\)(\\\\)*" '' \ double_string '"' (?<!\\)(\\\\)*" '' \
single_string "'" "'" '' \ single_string "'" "'" '' \
comment '#' '$' '' comment '#' '$' ''

View File

@ -1,7 +1,7 @@
# define color scheme # define color scheme
face value red face value red
face type yellow face type yellow
face identifier cyan face identifier green
face string magenta face string magenta
face error default,red face error default,red
face keyword blue face keyword blue

View File

@ -712,10 +712,7 @@ HighlighterAndId reference_factory(HighlighterParameters params)
}}; }};
} }
namespace RegionHighlight struct RegexMatch
{
struct Match
{ {
size_t timestamp; size_t timestamp;
LineCount line; LineCount line;
@ -725,9 +722,9 @@ struct Match
ByteCoord begin_coord() const { return { line, begin }; } ByteCoord begin_coord() const { return { line, begin }; }
ByteCoord end_coord() const { return { line, end }; } ByteCoord end_coord() const { return { line, end }; }
}; };
using MatchList = std::vector<Match>; using RegexMatchList = std::vector<RegexMatch>;
void find_matches(const Buffer& buffer, MatchList& matches, const Regex& regex) void find_matches(const Buffer& buffer, RegexMatchList& matches, const Regex& regex)
{ {
const size_t buf_timestamp = buffer.timestamp(); const size_t buf_timestamp = buffer.timestamp();
for (auto line = 0_line, end = buffer.line_count(); line < end; ++line) for (auto line = 0_line, end = buffer.line_count(); line < end; ++line)
@ -743,7 +740,7 @@ void find_matches(const Buffer& buffer, MatchList& matches, const Regex& regex)
} }
void update_matches(const Buffer& buffer, memoryview<LineModification> modifs, void update_matches(const Buffer& buffer, memoryview<LineModification> modifs,
MatchList& matches, const Regex& regex) RegexMatchList& matches, const Regex& regex)
{ {
const size_t buf_timestamp = buffer.timestamp(); const size_t buf_timestamp = buffer.timestamp();
// remove out of date matches and update line for others // remove out of date matches and update line for others
@ -796,29 +793,29 @@ void update_matches(const Buffer& buffer, memoryview<LineModification> modifs,
} }
} }
std::inplace_merge(matches.begin(), matches.begin() + pivot, matches.end(), std::inplace_merge(matches.begin(), matches.begin() + pivot, matches.end(),
[](const Match& lhs, const Match& rhs) { [](const RegexMatch& lhs, const RegexMatch& rhs) {
return lhs.begin_coord() < rhs.begin_coord(); return lhs.begin_coord() < rhs.begin_coord();
}); });
} }
struct RegionMatches struct RegionMatches
{ {
MatchList begin_matches; RegexMatchList begin_matches;
MatchList end_matches; RegexMatchList end_matches;
MatchList recurse_matches; RegexMatchList recurse_matches;
static bool compare_to_begin(const Match& lhs, ByteCoord rhs) static bool compare_to_begin(const RegexMatch& lhs, ByteCoord rhs)
{ {
return lhs.begin_coord() < rhs; return lhs.begin_coord() < rhs;
} }
MatchList::const_iterator find_next_begin(ByteCoord pos) const RegexMatchList::const_iterator find_next_begin(ByteCoord pos) const
{ {
return std::lower_bound(begin_matches.begin(), begin_matches.end(), return std::lower_bound(begin_matches.begin(), begin_matches.end(),
pos, compare_to_begin); pos, compare_to_begin);
} }
MatchList::const_iterator find_matching_end(ByteCoord beg_pos) const RegexMatchList::const_iterator find_matching_end(ByteCoord beg_pos) const
{ {
auto end_it = end_matches.begin(); auto end_it = end_matches.begin();
auto rec_it = recurse_matches.begin(); auto rec_it = recurse_matches.begin();
@ -858,10 +855,10 @@ struct RegionDesc
RegionMatches find_matches(const Buffer& buffer) const RegionMatches find_matches(const Buffer& buffer) const
{ {
RegionMatches res; RegionMatches res;
RegionHighlight::find_matches(buffer, res.begin_matches, m_begin); Kakoune::find_matches(buffer, res.begin_matches, m_begin);
RegionHighlight::find_matches(buffer, res.end_matches, m_end); Kakoune::find_matches(buffer, res.end_matches, m_end);
if (not m_recurse.empty()) if (not m_recurse.empty())
RegionHighlight::find_matches(buffer, res.recurse_matches, m_recurse); Kakoune::find_matches(buffer, res.recurse_matches, m_recurse);
return res; return res;
} }
@ -869,138 +866,19 @@ struct RegionDesc
memoryview<LineModification> modifs, memoryview<LineModification> modifs,
RegionMatches& matches) const RegionMatches& matches) const
{ {
RegionHighlight::update_matches(buffer, modifs, matches.begin_matches, m_begin); Kakoune::update_matches(buffer, modifs, matches.begin_matches, m_begin);
RegionHighlight::update_matches(buffer, modifs, matches.end_matches, m_end); Kakoune::update_matches(buffer, modifs, matches.end_matches, m_end);
if (not m_recurse.empty()) if (not m_recurse.empty())
RegionHighlight::update_matches(buffer, modifs, matches.recurse_matches, m_recurse); Kakoune::update_matches(buffer, modifs, matches.recurse_matches, m_recurse);
} }
}; };
struct RegionHighlighter struct RegionsHighlighter
{
public:
RegionHighlighter(Regex begin, Regex end, Regex recurse = Regex{})
: m_region{ std::move(begin), std::move(end), std::move(recurse) }
{
if (m_region.m_begin.empty() or m_region.m_end.empty())
throw runtime_error("invalid regex for region highlighter");
}
void operator()(HierachicalHighlighter::GroupMap groups, const Context& context,
HighlightFlags flags, DisplayBuffer& display_buffer)
{
if (flags != HighlightFlags::Highlight)
return;
auto it = groups.find("content");
if (it == groups.end())
return;
auto range = display_buffer.range();
const auto& buffer = context.buffer();
auto& regions = update_cache_ifn(buffer);
auto begin = std::lower_bound(regions.begin(), regions.end(), range.first,
[](const Region& r, ByteCoord c) { return r.end < c; });
auto end = std::lower_bound(begin, regions.end(), range.second,
[](const Region& r, ByteCoord c) { return r.begin < c; });
auto correct = [&](ByteCoord c) -> ByteCoord {
if (buffer[c.line].length() == c.column)
return {c.line+1, 0};
return c;
};
for (; begin != end; ++begin)
apply_highlighter(context, flags, display_buffer,
correct(begin->begin), correct(begin->end),
it->second);
}
private:
RegionDesc m_region;
struct Region
{
ByteCoord begin;
ByteCoord end;
};
using RegionList = std::vector<Region>;
struct Cache
{
size_t timestamp = 0;
RegionMatches matches;
RegionList regions;
};
BufferSideCache<Cache> m_cache;
const RegionList& update_cache_ifn(const Buffer& buffer)
{
Cache& cache = m_cache.get(buffer);
const size_t buf_timestamp = buffer.timestamp();
if (cache.timestamp == buf_timestamp)
return cache.regions;
if (cache.timestamp == 0)
cache.matches = m_region.find_matches(buffer);
else
{
auto modifs = compute_line_modifications(buffer, cache.timestamp);
m_region.update_matches(buffer, modifs, cache.matches);
}
cache.regions.clear();
for (auto beg_it = cache.matches.begin_matches.cbegin();
beg_it != cache.matches.begin_matches.end(); )
{
auto end_it = cache.matches.find_matching_end(beg_it->end_coord());
if (end_it == cache.matches.end_matches.end())
{
cache.regions.push_back({ {beg_it->line, beg_it->begin},
buffer.end_coord() });
break;
}
else
{
cache.regions.push_back({ beg_it->begin_coord(),
end_it->end_coord() });
beg_it = cache.matches.find_next_begin(end_it->end_coord());
}
}
cache.timestamp = buf_timestamp;
return cache.regions;
}
};
HighlighterAndId region_factory(HighlighterParameters params)
{
try
{
if (params.size() != 3 && params.size() != 4)
throw runtime_error("wrong parameter count");
Regex begin{params[1], Regex::nosubs | Regex::optimize };
Regex end{params[2], Regex::nosubs | Regex::optimize };
Regex recurse;
if (params.size() == 4)
recurse = Regex{params[3], Regex::nosubs | Regex::optimize };
return {params[0],
HierachicalHighlighter(RegionHighlighter(std::move(begin),
std::move(end),
std::move(recurse)),
{ { "content", HighlighterGroup{} } })};
}
catch (boost::regex_error& err)
{
throw runtime_error(String("regex error: ") + err.what());
}
}
struct MultiRegionHighlighter
{ {
public: public:
using NamedRegionDescList = std::vector<std::pair<String, RegionDesc>>; using NamedRegionDescList = std::vector<std::pair<String, RegionDesc>>;
MultiRegionHighlighter(NamedRegionDescList regions, String default_group) RegionsHighlighter(NamedRegionDescList regions, String default_group)
: m_regions{std::move(regions)}, m_default_group{std::move(default_group)} : m_regions{std::move(regions)}, m_default_group{std::move(default_group)}
{ {
if (m_regions.empty()) if (m_regions.empty())
@ -1076,7 +954,7 @@ private:
}; };
BufferSideCache<Cache> m_cache; BufferSideCache<Cache> m_cache;
using RegionAndMatch = std::pair<size_t, MatchList::const_iterator>; using RegionAndMatch = std::pair<size_t, RegexMatchList::const_iterator>;
// find the begin closest to pos in all matches // find the begin closest to pos in all matches
RegionAndMatch find_next_begin(const Cache& cache, ByteCoord pos) const RegionAndMatch find_next_begin(const Cache& cache, ByteCoord pos) const
@ -1156,7 +1034,7 @@ private:
} }
}; };
HighlighterAndId multi_region_factory(HighlighterParameters params) HighlighterAndId regions_factory(HighlighterParameters params)
{ {
try try
{ {
@ -1169,7 +1047,7 @@ HighlighterAndId multi_region_factory(HighlighterParameters params)
if ((parser.positional_count() % 4) != 1) if ((parser.positional_count() % 4) != 1)
throw runtime_error("wrong parameter count, expect <id> (<group name> <begin> <end> <recurse>)+"); throw runtime_error("wrong parameter count, expect <id> (<group name> <begin> <end> <recurse>)+");
MultiRegionHighlighter::NamedRegionDescList regions; RegionsHighlighter::NamedRegionDescList regions;
id_map<HighlighterGroup> groups; id_map<HighlighterGroup> groups;
for (size_t i = 1; i < parser.positional_count(); i += 4) for (size_t i = 1; i < parser.positional_count(); i += 4)
{ {
@ -1194,7 +1072,7 @@ HighlighterAndId multi_region_factory(HighlighterParameters params)
return {parser[0], return {parser[0],
HierachicalHighlighter( HierachicalHighlighter(
MultiRegionHighlighter(std::move(regions), std::move(default_group)), std::move(groups))}; RegionsHighlighter(std::move(regions), std::move(default_group)), std::move(groups))};
} }
catch (boost::regex_error& err) catch (boost::regex_error& err)
{ {
@ -1202,8 +1080,6 @@ HighlighterAndId multi_region_factory(HighlighterParameters params)
} }
} }
}
void register_highlighters() void register_highlighters()
{ {
HighlighterRegistry& registry = HighlighterRegistry::instance(); HighlighterRegistry& registry = HighlighterRegistry::instance();
@ -1219,8 +1095,7 @@ void register_highlighters()
registry.register_func("flag_lines", flag_lines_factory); registry.register_func("flag_lines", flag_lines_factory);
registry.register_func("line_option", highlight_line_option_factory); registry.register_func("line_option", highlight_line_option_factory);
registry.register_func("ref", reference_factory); registry.register_func("ref", reference_factory);
registry.register_func("region", RegionHighlight::region_factory); registry.register_func("regions", regions_factory);
registry.register_func("multi_region", RegionHighlight::multi_region_factory);
} }
} }