mirror of
https://github.com/hyprwm/hyprlang.git
synced 2026-05-07 00:18:08 +02:00
configvalue: add an extended config value getter (#93)
This commit is contained in:
parent
7833ff33b2
commit
090117506d
4 changed files with 106 additions and 37 deletions
|
|
@ -389,6 +389,18 @@ namespace Hyprlang {
|
|||
*/
|
||||
CConfigValue* getSpecialConfigValuePtr(const char* category, const char* name, const char* key = nullptr);
|
||||
|
||||
/*!
|
||||
Get a basic or special category's config value ptr.
|
||||
|
||||
Syntax:
|
||||
- `name` -> `general:gaps_out`
|
||||
- `category[key]:name` -> `windowrule[name]:enable`
|
||||
|
||||
\note Prefer `getConfigValuePtr` or `getSpecialConfigValuePtr` to avoid unnecessary lookup and parsing.
|
||||
\warning The pointer is temporary and only valid for a brief moment
|
||||
*/
|
||||
CConfigValue* getAnyConfigValuePtr(const char* name);
|
||||
|
||||
/*!
|
||||
Get a config value's stored value. Empty on fail
|
||||
*/
|
||||
|
|
@ -409,6 +421,22 @@ namespace Hyprlang {
|
|||
return val->getValue();
|
||||
}
|
||||
|
||||
/*!
|
||||
Get a basic or special config value's stored value. Empty on fail.
|
||||
|
||||
Syntax:
|
||||
- `name` -> `general:gaps_out`
|
||||
- `category[key]:name` -> `windowrule[name]:enable`
|
||||
|
||||
\note Prefer `getConfigValue` or `getSpecialConfigValue` to avoid unnecessary lookup and parsing.
|
||||
*/
|
||||
std::any getAnyConfigValue(const char* name) {
|
||||
CConfigValue* val = getAnyConfigValuePtr(name);
|
||||
if (!val)
|
||||
return {};
|
||||
return val->getValue();
|
||||
}
|
||||
|
||||
/*!
|
||||
Check whether a special category with the provided key value exists
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,20 @@ static size_t seekABIStructSize(const void* begin, size_t startOffset, size_t ma
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SParsedConfigName parseConfigName(const char* name) {
|
||||
const std::string NAME = name;
|
||||
const auto L = NAME.find('[');
|
||||
const auto R = NAME.find("]:", L);
|
||||
|
||||
if (L != std::string::npos && R != std::string::npos)
|
||||
return SParsedConfigName{
|
||||
.category = NAME.substr(0, L),
|
||||
.key = NAME.substr(L + 1, R - L - 1),
|
||||
.name = NAME.substr(R + 2),
|
||||
};
|
||||
return SParsedConfigName{.name = name};
|
||||
}
|
||||
|
||||
static std::expected<std::string, eGetNextLineFailure> getNextLine(std::istream& str, int& rawLineNum, int& lineNum) {
|
||||
std::string line = "";
|
||||
std::string nextLine = "";
|
||||
|
|
@ -293,50 +307,44 @@ std::pair<bool, CParseResult> CConfig::configSetValueSafe(const std::string& com
|
|||
// TODO: all this sucks xD
|
||||
|
||||
SSpecialCategory* overrideSpecialCat = nullptr;
|
||||
const auto parsedName = parseConfigName(valueName.c_str());
|
||||
|
||||
if (valueName.contains('[') && valueName.contains(']')) {
|
||||
const auto L = valueName.find_first_of('[');
|
||||
const auto R = valueName.find_last_of(']');
|
||||
if (!parsedName.category.empty()) {
|
||||
impl->currentSpecialKey = parsedName.key;
|
||||
valueName = parsedName.category + ":" + parsedName.name;
|
||||
|
||||
if (L < R) {
|
||||
const auto CATKEY = valueName.substr(L + 1, R - L - 1);
|
||||
impl->currentSpecialKey = CATKEY;
|
||||
for (auto& sc : impl->specialCategoryDescriptors) {
|
||||
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
|
||||
continue;
|
||||
|
||||
valueName = valueName.substr(0, L) + valueName.substr(R + 1);
|
||||
|
||||
for (auto& sc : impl->specialCategoryDescriptors) {
|
||||
if (sc->key.empty() || !valueName.starts_with(sc->name + ":"))
|
||||
bool keyExists = false;
|
||||
for (const auto& specialCat : impl->specialCategories) {
|
||||
if (specialCat->key != sc->key || specialCat->name != sc->name)
|
||||
continue;
|
||||
|
||||
bool keyExists = false;
|
||||
for (const auto& specialCat : impl->specialCategories) {
|
||||
if (specialCat->key != sc->key || specialCat->name != sc->name)
|
||||
continue;
|
||||
if (parsedName.key != std::string_view{std::any_cast<const char*>(specialCat->values[sc->key].getValue())})
|
||||
continue;
|
||||
|
||||
if (CATKEY != std::string_view{std::any_cast<const char*>(specialCat->values[sc->key].getValue())})
|
||||
continue;
|
||||
|
||||
// existing special
|
||||
keyExists = true;
|
||||
overrideSpecialCat = specialCat.get();
|
||||
}
|
||||
|
||||
if (keyExists)
|
||||
break;
|
||||
|
||||
// if it doesn't exist, make it
|
||||
const auto PCAT = impl->specialCategories.emplace_back(std::make_unique<SSpecialCategory>()).get();
|
||||
PCAT->descriptor = sc.get();
|
||||
PCAT->name = sc->name;
|
||||
PCAT->key = sc->key;
|
||||
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue(CATKEY.c_str()));
|
||||
|
||||
applyDefaultsToCat(*PCAT);
|
||||
|
||||
PCAT->values[sc->key].setFrom(CATKEY);
|
||||
overrideSpecialCat = PCAT;
|
||||
break;
|
||||
// existing special
|
||||
keyExists = true;
|
||||
overrideSpecialCat = specialCat.get();
|
||||
}
|
||||
|
||||
if (keyExists)
|
||||
break;
|
||||
|
||||
// if it doesn't exist, make it
|
||||
const auto PCAT = impl->specialCategories.emplace_back(std::make_unique<SSpecialCategory>()).get();
|
||||
PCAT->descriptor = sc.get();
|
||||
PCAT->name = sc->name;
|
||||
PCAT->key = sc->key;
|
||||
addSpecialConfigValue(sc->name.c_str(), sc->key.c_str(), CConfigValue(parsedName.key.c_str()));
|
||||
|
||||
applyDefaultsToCat(*PCAT);
|
||||
|
||||
PCAT->values[sc->key].setFrom(parsedName.key);
|
||||
overrideSpecialCat = PCAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1109,6 +1117,13 @@ CConfigValue* CConfig::getSpecialConfigValuePtr(const char* category, const char
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CConfigValue* CConfig::getAnyConfigValuePtr(const char* name) {
|
||||
const auto parsedName = parseConfigName(name);
|
||||
if (!parsedName.category.empty())
|
||||
return getSpecialConfigValuePtr(parsedName.category.c_str(), parsedName.name.c_str(), parsedName.key.c_str());
|
||||
return getConfigValuePtr(name);
|
||||
}
|
||||
|
||||
void CConfig::registerHandler(PCONFIGHANDLERFUNC func, const char* name, SHandlerOptions options_) {
|
||||
SHandlerOptions options;
|
||||
std::memcpy(&options, &options_, seekABIStructSize(&options_, 0, sizeof(SHandlerOptions)));
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ struct SSpecialCategory {
|
|||
size_t anonymousID = 0;
|
||||
};
|
||||
|
||||
struct SParsedConfigName {
|
||||
std::string category = "";
|
||||
std::string key = "";
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
enum eGetNextLineFailure : uint8_t {
|
||||
GETNEXTLINEFAILURE_EOF = 0,
|
||||
GETNEXTLINEFAILURE_BACKSLASH,
|
||||
|
|
|
|||
|
|
@ -385,6 +385,26 @@ int main(int argc, char** argv, char** envp) {
|
|||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value1", KEYS2[1].c_str())), 12);
|
||||
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested1:nested2:value2", KEYS2[1].c_str())), 13);
|
||||
|
||||
std::cout << " → Testing the unified config value getter\n";
|
||||
// check against expected counterpart
|
||||
EXPECT(std::any_cast<int64_t>(config.getAnyConfigValue("testInt")), std::any_cast<int64_t>(config.getConfigValue("testInt")));
|
||||
EXPECT(std::any_cast<float>(config.getAnyConfigValue("testFloat")), std::any_cast<float>(config.getConfigValue("testFloat")));
|
||||
EXPECT(std::any_cast<const char*>(config.getAnyConfigValue("testString")), std::any_cast<const char*>(config.getConfigValue("testString")));
|
||||
EXPECT(std::any_cast<int64_t>(config.getAnyConfigValue("special[a]:value")), std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "a")));
|
||||
EXPECT(std::any_cast<int64_t>(config.getAnyConfigValue("special[b]:value")), std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "b")));
|
||||
EXPECT(std::any_cast<int64_t>(config.getAnyConfigValue("special[]:value")), std::any_cast<int64_t>(config.getSpecialConfigValue("special", "value", "")));
|
||||
EXPECT(std::any_cast<int64_t>(config.getAnyConfigValue("specialAnonymousNested[c]:nested:value1")),
|
||||
std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymousNested", "nested:value1", "c")));
|
||||
// check against malformed
|
||||
EXPECT(config.getAnyConfigValuePtr("[a]:value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special[[a]:value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special[[a]]:value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special[a]]:value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special[a]value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special[avalue"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("special]:a[value"), nullptr);
|
||||
EXPECT(config.getAnyConfigValuePtr("speciala]:value"), nullptr);
|
||||
|
||||
// test sourcing
|
||||
std::cout << " → Testing sourcing\n";
|
||||
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:pink")), (Hyprlang::INT)0xFFc800c8);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue