core: handle scoped keywords if flags are not allowed (#49)

* core: handle scoped keywords if flags are not allowed

* chore: formatting

* test: add test cases for unintended categoryKeyword config options

* fix: use at() instead of []
This commit is contained in:
Aurélien Brabant 2024-07-07 18:05:23 +02:00 committed by GitHub
parent db8c528aac
commit 095f54b910
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 7 deletions

View File

@ -563,9 +563,28 @@ CParseResult CConfig::parseLine(std::string line, bool dynamic) {
return parseVariable(LHS, RHS, dynamic); return parseVariable(LHS, RHS, dynamic);
bool found = false; bool found = false;
for (auto& h : impl->handlers) { for (auto& h : impl->handlers) {
if (!h.options.allowFlags && h.name != LHS) if (!h.options.allowFlags) {
continue; // we want to handle potentially nested keywords and ensure
// we only call the handler if they are scoped correctly.
size_t colon = 0;
size_t idx = 0;
size_t depth = 0;
while ((colon = h.name.find(":", idx)) != std::string::npos && impl->categories.size() > depth) {
auto actual = h.name.substr(idx, colon - idx);
if (actual != impl->categories[depth])
break;
idx = colon + 1;
++depth;
}
if (depth != impl->categories.size() || h.name.substr(idx) != LHS)
continue;
}
if (h.options.allowFlags && (!LHS.starts_with(h.name) || LHS.contains(':') /* avoid cases where a category is called the same as a handler */)) if (h.options.allowFlags && (!LHS.starts_with(h.name) || LHS.contains(':') /* avoid cases where a category is called the same as a handler */))
continue; continue;

View File

@ -28,6 +28,8 @@ errorVariable = true
# hyprlang noerror false # hyprlang noerror false
categoryKeyword = oops, this one shouldn't call the handler, not fun
testCategory { testCategory {
testValueInt = 123456 testValueInt = 123456
testValueHex = 0xF testValueHex = 0xF
@ -41,7 +43,12 @@ testCategory {
nested2 { nested2 {
testValueNest = 1 testValueNest = 1
} }
categoryKeyword = this one should not either
} }
categoryKeyword = we are having fun
categoryKeyword = so much fun
categoryKeyword = im the fun one at parties
} }
$SPECIALVAL1 = 1 $SPECIALVAL1 = 1

View File

@ -23,12 +23,13 @@ namespace Colors {
} }
// globals for testing // globals for testing
bool barrelRoll = false; bool barrelRoll = false;
std::string flagsFound = ""; std::string flagsFound = "";
Hyprlang::CConfig* pConfig = nullptr; Hyprlang::CConfig* pConfig = nullptr;
std::string currentPath = ""; std::string currentPath = "";
static std::vector<std::string> categoryKeywordActualValues;
static Hyprlang::CParseResult handleDoABarrelRoll(const char* COMMAND, const char* VALUE) { static Hyprlang::CParseResult handleDoABarrelRoll(const char* COMMAND, const char* VALUE) {
if (std::string(VALUE) == "woohoo, some, params") if (std::string(VALUE) == "woohoo, some, params")
barrelRoll = true; barrelRoll = true;
@ -44,6 +45,12 @@ static Hyprlang::CParseResult handleFlagsTest(const char* COMMAND, const char* V
return result; return result;
} }
static Hyprlang::CParseResult handleCategoryKeyword(const char* COMMAND, const char* VALUE) {
categoryKeywordActualValues.push_back(VALUE);
return Hyprlang::CParseResult();
}
static Hyprlang::CParseResult handleSource(const char* COMMAND, const char* VALUE) { static Hyprlang::CParseResult handleSource(const char* COMMAND, const char* VALUE) {
std::string PATH = std::filesystem::canonical(currentPath + "/" + VALUE); std::string PATH = std::filesystem::canonical(currentPath + "/" + VALUE);
return pConfig->parseFile(PATH.c_str()); return pConfig->parseFile(PATH.c_str());
@ -88,12 +95,14 @@ int main(int argc, char** argv, char** envp) {
config.addConfigValue("testStringColon", ""); config.addConfigValue("testStringColon", "");
config.addConfigValue("testEnv", ""); config.addConfigValue("testEnv", "");
config.addConfigValue("testVar", (Hyprlang::INT)0); config.addConfigValue("testVar", (Hyprlang::INT)0);
config.addConfigValue("categoryKeyword", (Hyprlang::STRING) "");
config.addConfigValue("testStringQuotes", ""); config.addConfigValue("testStringQuotes", "");
config.addConfigValue("testStringRecursive", ""); config.addConfigValue("testStringRecursive", "");
config.addConfigValue("testCategory:testValueInt", (Hyprlang::INT)0); config.addConfigValue("testCategory:testValueInt", (Hyprlang::INT)0);
config.addConfigValue("testCategory:testValueHex", (Hyprlang::INT)0xA); config.addConfigValue("testCategory:testValueHex", (Hyprlang::INT)0xA);
config.addConfigValue("testCategory:nested1:testValueNest", (Hyprlang::INT)0); config.addConfigValue("testCategory:nested1:testValueNest", (Hyprlang::INT)0);
config.addConfigValue("testCategory:nested1:nested2:testValueNest", (Hyprlang::INT)0); config.addConfigValue("testCategory:nested1:nested2:testValueNest", (Hyprlang::INT)0);
config.addConfigValue("testCategory:nested1:categoryKeyword", (Hyprlang::STRING) "");
config.addConfigValue("testDefault", (Hyprlang::INT)123); config.addConfigValue("testDefault", (Hyprlang::INT)123);
config.addConfigValue("testCategory:testColor1", (Hyprlang::INT)0); config.addConfigValue("testCategory:testColor1", (Hyprlang::INT)0);
config.addConfigValue("testCategory:testColor2", (Hyprlang::INT)0); config.addConfigValue("testCategory:testColor2", (Hyprlang::INT)0);
@ -107,6 +116,7 @@ int main(int argc, char** argv, char** envp) {
config.registerHandler(&handleDoABarrelRoll, "doABarrelRoll", {false}); config.registerHandler(&handleDoABarrelRoll, "doABarrelRoll", {false});
config.registerHandler(&handleFlagsTest, "flags", {true}); config.registerHandler(&handleFlagsTest, "flags", {true});
config.registerHandler(&handleSource, "source", {false}); config.registerHandler(&handleSource, "source", {false});
config.registerHandler(&handleCategoryKeyword, "testCategory:categoryKeyword", {false});
config.addSpecialCategory("special", {"key"}); config.addSpecialCategory("special", {"key"});
config.addSpecialConfigValue("special", "value", (Hyprlang::INT)0); config.addSpecialConfigValue("special", "value", (Hyprlang::INT)0);
@ -149,6 +159,8 @@ int main(int argc, char** argv, char** envp) {
EXPECT(std::any_cast<int64_t>(config.getConfigValue("testCategory:testColor2")), (Hyprlang::INT)0xFF000000); EXPECT(std::any_cast<int64_t>(config.getConfigValue("testCategory:testColor2")), (Hyprlang::INT)0xFF000000);
EXPECT(std::any_cast<int64_t>(config.getConfigValue("testCategory:testColor3")), (Hyprlang::INT)0x22ffeeff); EXPECT(std::any_cast<int64_t>(config.getConfigValue("testCategory:testColor3")), (Hyprlang::INT)0x22ffeeff);
EXPECT(std::any_cast<const char*>(config.getConfigValue("testStringColon")), std::string{"ee:ee:ee"}); EXPECT(std::any_cast<const char*>(config.getConfigValue("testStringColon")), std::string{"ee:ee:ee"});
EXPECT(std::any_cast<const char*>(config.getConfigValue("categoryKeyword")), std::string{"oops, this one shouldn't call the handler, not fun"});
EXPECT(std::any_cast<const char*>(config.getConfigValue("testCategory:nested1:categoryKeyword")), std::string{"this one should not either"});
// test static values // test static values
std::cout << " → Testing static values\n"; std::cout << " → Testing static values\n";
@ -162,6 +174,10 @@ int main(int argc, char** argv, char** envp) {
EXPECT(barrelRoll, true); EXPECT(barrelRoll, true);
EXPECT(flagsFound, std::string{"abc"}); EXPECT(flagsFound, std::string{"abc"});
EXPECT(categoryKeywordActualValues.at(0), "we are having fun");
EXPECT(categoryKeywordActualValues.at(1), "so much fun");
EXPECT(categoryKeywordActualValues.at(2), "im the fun one at parties");
// test dynamic // test dynamic
std::cout << " → Testing dynamic\n"; std::cout << " → Testing dynamic\n";
barrelRoll = false; barrelRoll = false;