Allow faces to reference faces

Fixes #102
This commit is contained in:
Maxime Coste 2014-08-19 23:10:56 +01:00
parent bea53d09b2
commit d78e331304
2 changed files with 49 additions and 20 deletions

View File

@ -36,13 +36,17 @@ static Face parse_face(StringView facedesc)
Face FaceRegistry::operator[](const String& facedesc) Face FaceRegistry::operator[](const String& facedesc)
{ {
auto it = m_aliases.find(facedesc); auto it = m_aliases.find(facedesc);
if (it != m_aliases.end()) while (it != m_aliases.end())
return it->second; {
if (it->second.alias.empty())
return it->second.face;
it = m_aliases.find(it->second.alias);
}
return parse_face(facedesc); return parse_face(facedesc);
} }
void FaceRegistry::register_alias(const String& name, const String& facedesc, void FaceRegistry::register_alias(const String& name, const String& facedesc,
bool override) bool override)
{ {
if (not override and m_aliases.find(name) != m_aliases.end()) if (not override and m_aliases.find(name) != m_aliases.end())
throw runtime_error("alias '" + name + "' already defined"); throw runtime_error("alias '" + name + "' already defined");
@ -51,9 +55,26 @@ void FaceRegistry::register_alias(const String& name, const String& facedesc,
find_if(name, [](char c){ return not isalnum(c); }) != name.end()) find_if(name, [](char c){ return not isalnum(c); }) != name.end())
throw runtime_error("invalid alias name"); throw runtime_error("invalid alias name");
FaceOrAlias& alias = m_aliases[name];
auto it = m_aliases.find(facedesc); auto it = m_aliases.find(facedesc);
m_aliases[name] = (it != m_aliases.end()) ? if (it != m_aliases.end())
it->second : parse_face(facedesc); {
while (it != m_aliases.end())
{
if (it->second.alias.empty())
break;
if (it->second.alias == name)
throw runtime_error("face cycle detected");
it = m_aliases.find(it->second.alias);
}
alias.alias = facedesc;
}
else
{
alias.alias = "";
alias.face = parse_face(facedesc);
}
} }
CandidateList FaceRegistry::complete_alias_name(StringView prefix, CandidateList FaceRegistry::complete_alias_name(StringView prefix,
@ -71,20 +92,20 @@ CandidateList FaceRegistry::complete_alias_name(StringView prefix,
FaceRegistry::FaceRegistry() FaceRegistry::FaceRegistry()
: m_aliases{ : m_aliases{
{ "PrimarySelection", { Colors::Cyan, Colors::Blue } }, { "PrimarySelection", Face{ Colors::Cyan, Colors::Blue } },
{ "SecondarySelection", { Colors::Black, Colors::Blue } }, { "SecondarySelection", Face{ Colors::Black, Colors::Blue } },
{ "PrimaryCursor", { Colors::Black, Colors::White } }, { "PrimaryCursor", Face{ Colors::Black, Colors::White } },
{ "SecondaryCursor", { Colors::Black, Colors::White } }, { "SecondaryCursor", Face{ Colors::Black, Colors::White } },
{ "LineNumbers", { Colors::Default, Colors::Default } }, { "LineNumbers", Face{ Colors::Default, Colors::Default } },
{ "MenuForeground", { Colors::White, Colors::Blue } }, { "MenuForeground", Face{ Colors::White, Colors::Blue } },
{ "MenuBackground", { Colors::Blue, Colors::White } }, { "MenuBackground", Face{ Colors::Blue, Colors::White } },
{ "Information", { Colors::Black, Colors::Yellow } }, { "Information", Face{ Colors::Black, Colors::Yellow } },
{ "Error", { Colors::Black, Colors::Red } }, { "Error", Face{ Colors::Black, Colors::Red } },
{ "StatusLine", { Colors::Cyan, Colors::Default } }, { "StatusLine", Face{ Colors::Cyan, Colors::Default } },
{ "StatusCursor", { Colors::Black, Colors::Cyan } }, { "StatusCursor", Face{ Colors::Black, Colors::Cyan } },
{ "Prompt", { Colors::Yellow, Colors::Default } }, { "Prompt", Face{ Colors::Yellow, Colors::Default } },
{ "MatchingChar", { Colors::Default, Colors::Default, Attribute::Underline } }, { "MatchingChar", Face{ Colors::Default, Colors::Default, Attribute::Underline } },
{ "Search", { Colors::Default, Colors::Default, Attribute::Underline } }, { "Search", Face{ Colors::Default, Colors::Default, Attribute::Underline } },
} }
{} {}

View File

@ -22,7 +22,15 @@ public:
CandidateList complete_alias_name(StringView prefix, CandidateList complete_alias_name(StringView prefix,
ByteCount cursor_pos) const; ByteCount cursor_pos) const;
private: private:
std::unordered_map<String, Face> m_aliases; struct FaceOrAlias
{
Face face;
String alias;
FaceOrAlias(Face face = Face{}) : face(face) {}
};
std::unordered_map<String, FaceOrAlias> m_aliases;
}; };
inline Face get_face(const String& facedesc) inline Face get_face(const String& facedesc)