Pre-parse face specs in Highlighters
Re-parsing face specs can be expensive as highlighters can be called many times during a redraw with nested regions.
This commit is contained in:
parent
e0728d3434
commit
5a867ebdd1
|
@ -7,7 +7,7 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
static FaceRegistry::FaceSpec parse_face(StringView facedesc)
|
FaceSpec parse_face(StringView facedesc)
|
||||||
{
|
{
|
||||||
constexpr StringView invalid_face_error = "invalid face description, expected [<fg>][,<bg>[,<underline>]][+<attr>][@base] or just [base]";
|
constexpr StringView invalid_face_error = "invalid face description, expected [<fg>][,<bg>[,<underline>]][+<attr>][@base] or just [base]";
|
||||||
if (all_of(facedesc, [](char c){ return is_word(c); }) and not is_color_name(facedesc))
|
if (all_of(facedesc, [](char c){ return is_word(c); }) and not is_color_name(facedesc))
|
||||||
|
@ -33,7 +33,7 @@ static FaceRegistry::FaceSpec parse_face(StringView facedesc)
|
||||||
return spec.empty() ? Color::Default : str_to_color(spec);
|
return spec.empty() ? Color::Default : str_to_color(spec);
|
||||||
};
|
};
|
||||||
|
|
||||||
FaceRegistry::FaceSpec spec;
|
FaceSpec spec;
|
||||||
auto& face = spec.face;
|
auto& face = spec.face;
|
||||||
face.fg = parse_color({facedesc.begin(), std::min(bg_it, colors_end)});
|
face.fg = parse_color({facedesc.begin(), std::min(bg_it, colors_end)});
|
||||||
if (bg_it != facedesc.end())
|
if (bg_it != facedesc.end())
|
||||||
|
@ -111,6 +111,11 @@ Face FaceRegistry::operator[](StringView facedesc) const
|
||||||
return resolve_spec(parse_face(facedesc));
|
return resolve_spec(parse_face(facedesc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Face FaceRegistry::operator[](const FaceSpec& spec) const
|
||||||
|
{
|
||||||
|
return resolve_spec(spec);
|
||||||
|
}
|
||||||
|
|
||||||
Face FaceRegistry::resolve_spec(const FaceSpec& spec) const
|
Face FaceRegistry::resolve_spec(const FaceSpec& spec) const
|
||||||
{
|
{
|
||||||
if (spec.base.empty())
|
if (spec.base.empty())
|
||||||
|
|
|
@ -11,20 +11,24 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct FaceSpec
|
||||||
|
{
|
||||||
|
Face face = {};
|
||||||
|
String base = {};
|
||||||
|
|
||||||
|
friend bool operator==(const FaceSpec&, const FaceSpec&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
class FaceRegistry : public SafeCountable
|
class FaceRegistry : public SafeCountable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FaceRegistry(FaceRegistry& parent) : SafeCountable{}, m_parent(&parent) {}
|
FaceRegistry(FaceRegistry& parent) : SafeCountable{}, m_parent(&parent) {}
|
||||||
|
|
||||||
Face operator[](StringView facedesc) const;
|
Face operator[](StringView facedesc) const;
|
||||||
|
Face operator[](const FaceSpec& facespec) const;
|
||||||
void add_face(StringView name, StringView facedesc, bool override = false);
|
void add_face(StringView name, StringView facedesc, bool override = false);
|
||||||
void remove_face(StringView name);
|
void remove_face(StringView name);
|
||||||
|
|
||||||
struct FaceSpec
|
|
||||||
{
|
|
||||||
Face face = {};
|
|
||||||
String base = {};
|
|
||||||
};
|
|
||||||
using FaceMap = HashMap<String, FaceSpec, MemoryDomain::Faces>;
|
using FaceMap = HashMap<String, FaceSpec, MemoryDomain::Faces>;
|
||||||
|
|
||||||
auto flatten_faces() const
|
auto flatten_faces() const
|
||||||
|
@ -50,6 +54,7 @@ private:
|
||||||
FaceMap m_faces;
|
FaceMap m_faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FaceSpec parse_face(StringView facedesc);
|
||||||
String to_string(Face face);
|
String to_string(Face face);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,13 +143,12 @@ static std::unique_ptr<Highlighter> create_fill_highlighter(HighlighterParameter
|
||||||
if (params.size() != 1)
|
if (params.size() != 1)
|
||||||
throw runtime_error("wrong parameter count");
|
throw runtime_error("wrong parameter count");
|
||||||
|
|
||||||
const String& facespec = params[0];
|
return make_highlighter(
|
||||||
auto func = [facespec](HighlightContext context, DisplayBuffer& display_buffer, BufferRange range)
|
[spec=parse_face(params[0])](HighlightContext context, DisplayBuffer& display_buffer,
|
||||||
{
|
BufferRange range) {
|
||||||
highlight_range(display_buffer, range.begin, range.end, false,
|
highlight_range(display_buffer, range.begin, range.end, false,
|
||||||
apply_face(context.context.faces()[facespec]));
|
apply_face(context.context.faces()[spec]));
|
||||||
};
|
});
|
||||||
return make_highlighter(std::move(func));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -168,7 +167,7 @@ private:
|
||||||
ValueId m_id;
|
ValueId m_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FacesSpec = Vector<std::pair<size_t, String>, MemoryDomain::Highlight>;
|
using FacesSpec = Vector<std::pair<size_t, FaceSpec>, MemoryDomain::Highlight>;
|
||||||
|
|
||||||
const HighlighterDesc regex_desc = {
|
const HighlighterDesc regex_desc = {
|
||||||
"Parameters: <regex> <capture num>:<face> <capture num>:<face>...\n"
|
"Parameters: <regex> <capture num>:<face> <capture num>:<face>...\n"
|
||||||
|
@ -197,7 +196,7 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto faces = m_faces | transform([&faces = context.context.faces()](auto&& spec) {
|
const auto faces = m_faces | transform([&faces = context.context.faces()](auto&& spec) {
|
||||||
return spec.second.empty() ? Face{} : faces[spec.second];
|
return faces[spec.second];
|
||||||
}) | gather<Vector<Face>>();
|
}) | gather<Vector<Face>>();
|
||||||
|
|
||||||
const auto& matches = get_matches(context.context.buffer(), display_buffer.range(), range);
|
const auto& matches = get_matches(context.context.buffer(), display_buffer.range(), range);
|
||||||
|
@ -242,7 +241,7 @@ public:
|
||||||
if (capture < 0)
|
if (capture < 0)
|
||||||
throw runtime_error(format("capture name {} is neither a capture index, nor an existing capture name",
|
throw runtime_error(format("capture name {} is neither a capture index, nor an existing capture name",
|
||||||
capture_name));
|
capture_name));
|
||||||
faces.emplace_back(capture, String{colon+1, spec.end()});
|
faces.emplace_back(capture, parse_face({colon+1, spec.end()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<RegexHighlighter>(std::move(re), std::move(faces));
|
return std::make_unique<RegexHighlighter>(std::move(re), std::move(faces));
|
||||||
|
@ -272,11 +271,9 @@ private:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::sort(m_faces.begin(), m_faces.end(),
|
std::sort(m_faces.begin(), m_faces.end(),
|
||||||
[](const std::pair<size_t, String>& lhs,
|
[](auto&& lhs, auto&& rhs) { return lhs.first < rhs.first; });
|
||||||
const std::pair<size_t, String>& rhs)
|
|
||||||
{ return lhs.first < rhs.first; });
|
|
||||||
if (m_faces[0].first != 0)
|
if (m_faces[0].first != 0)
|
||||||
m_faces.emplace(m_faces.begin(), 0, String{});
|
m_faces.emplace(m_faces.begin(), 0, FaceSpec{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_matches(const Buffer& buffer, MatchList& matches, BufferRange range)
|
void add_matches(const Buffer& buffer, MatchList& matches, BufferRange range)
|
||||||
|
@ -411,14 +408,14 @@ std::unique_ptr<Highlighter> create_dynamic_regex_highlighter(HighlighterParamet
|
||||||
if (params.size() < 2)
|
if (params.size() < 2)
|
||||||
throw runtime_error("wrong parameter count");
|
throw runtime_error("wrong parameter count");
|
||||||
|
|
||||||
Vector<std::pair<String, String>> faces;
|
Vector<std::pair<String, FaceSpec>> faces;
|
||||||
for (auto& spec : params.subrange(1))
|
for (auto& spec : params.subrange(1))
|
||||||
{
|
{
|
||||||
auto colon = find(spec, ':');
|
auto colon = find(spec, ':');
|
||||||
if (colon == spec.end())
|
if (colon == spec.end())
|
||||||
throw runtime_error("wrong face spec: '" + spec +
|
throw runtime_error("wrong face spec: '" + spec +
|
||||||
"' expected <capture>:<facespec>");
|
"' expected <capture>:<facespec>");
|
||||||
faces.emplace_back(String{spec.begin(), colon}, String{colon+1, spec.end()});
|
faces.emplace_back(String{spec.begin(), colon}, parse_face({colon+1, spec.end()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto make_hl = [](auto& regex_getter, auto& face_getter) {
|
auto make_hl = [](auto& regex_getter, auto& face_getter) {
|
||||||
|
@ -440,7 +437,7 @@ std::unique_ptr<Highlighter> create_dynamic_regex_highlighter(HighlighterParamet
|
||||||
face.first));
|
face.first));
|
||||||
return FacesSpec{};
|
return FacesSpec{};
|
||||||
}
|
}
|
||||||
spec.emplace_back(capture, face.second);
|
spec.emplace_back(capture, std::move(face.second));
|
||||||
}
|
}
|
||||||
return spec;
|
return spec;
|
||||||
};
|
};
|
||||||
|
@ -1258,7 +1255,7 @@ void highlight_selections(HighlightContext context, DisplayBuffer& display_buffe
|
||||||
void expand_unprintable(HighlightContext context, DisplayBuffer& display_buffer, BufferRange)
|
void expand_unprintable(HighlightContext context, DisplayBuffer& display_buffer, BufferRange)
|
||||||
{
|
{
|
||||||
const auto& buffer = context.context.buffer();
|
const auto& buffer = context.context.buffer();
|
||||||
auto error = context.context.faces()["Error"];
|
auto error = context.context.faces()[FaceSpec{{}, "Error"}];
|
||||||
for (auto& line : display_buffer.lines())
|
for (auto& line : display_buffer.lines())
|
||||||
{
|
{
|
||||||
for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
|
for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user