API: add anonymous special categories

This commit is contained in:
Vaxry 2024-02-17 22:38:10 +00:00
parent 65a7f870a6
commit 378c3e273b
5 changed files with 62 additions and 10 deletions

View file

@ -131,6 +131,17 @@ namespace Hyprlang {
don't pop up an error if the config value is missing
*/
bool ignoreMissing = false;
/*!
Make this category an anonymous special one.
key has to be nullptr.
Anonymous special categories behave like key-based ones, but the keys
will be automatically assigned without user input.
\since 0.4.0
*/
bool anonymousKeyBased = false;
};
/*!

View file

@ -10,6 +10,10 @@
using namespace Hyprlang;
extern "C" char** environ;
// defines
inline constexpr const char* ANONYMOUS_KEY = "__hyprlang_internal_anonymous_key";
//
static std::string removeBeginEndSpacesTabs(std::string str) {
if (str.empty())
return str;
@ -107,14 +111,17 @@ void CConfig::addSpecialCategory(const char* name, SSpecialCategoryOptions optio
PDESC->key = options.key ? options.key : "";
PDESC->dontErrorOnMissing = options.ignoreMissing;
if (!options.key) {
if (!options.key && !options.anonymousKeyBased) {
const auto PCAT = impl->specialCategories.emplace_back(std::make_unique<SSpecialCategory>()).get();
PCAT->descriptor = PDESC;
PCAT->name = name;
PCAT->key = options.key ? options.key : "";
PCAT->key = "";
PCAT->isStatic = true;
if (!PCAT->key.empty())
addSpecialConfigValue(name, options.key, CConfigValue("0"));
}
if (options.anonymousKeyBased) {
PDESC->key = ANONYMOUS_KEY;
PDESC->anonymous = true;
}
// sort longest to shortest
@ -310,12 +317,26 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
if (VALUEIT != PCAT->values.end())
found = true;
if (sc->anonymous) {
// find suitable key
size_t biggest = 0;
for (auto& catt : impl->specialCategories) {
if (catt->anonymousID > biggest)
biggest = catt->anonymousID;
}
biggest++;
PCAT->values[ANONYMOUS_KEY].setFrom(std::to_string(biggest));
impl->currentSpecialKey = std::to_string(biggest);
PCAT->anonymousID = biggest;
} else {
if (VALUEIT == PCAT->values.end() || VALUEIT->first != sc->key) {
result.setError(std::format("special category's first value must be the key. Key for <{}> is <{}>", PCAT->name, PCAT->key));
return result;
}
impl->currentSpecialKey = value;
}
break;
}

View file

@ -41,6 +41,7 @@ struct SSpecialCategoryDescriptor {
std::string key = "";
std::unordered_map<std::string, SConfigDefaultValue> defaultValues;
bool dontErrorOnMissing = false;
bool anonymous = false;
};
struct SSpecialCategory {
@ -51,6 +52,9 @@ struct SSpecialCategory {
bool isStatic = false;
void applyDefaults();
// for easy anonymous ID'ing
size_t anonymousID = 0;
};
class CConfigImpl {

View file

@ -53,6 +53,14 @@ specialGeneric {
}
}
specialAnonymous {
value = 2
}
specialAnonymous {
value = 3
}
testCategory:testValueHex = 0xFFfFaAbB
testStringQuotes = "Hello World!"

View file

@ -108,6 +108,9 @@ int main(int argc, char** argv, char** envp) {
config.addSpecialCategory("special", {"key"});
config.addSpecialConfigValue("special", "value", (Hyprlang::INT)0);
config.addSpecialCategory("specialAnonymous", {nullptr, false, true});
config.addSpecialConfigValue("specialAnonymous", "value", (Hyprlang::INT)0);
config.commence();
config.addSpecialCategory("specialGeneric:one", {nullptr, true});
@ -194,6 +197,11 @@ int main(int argc, char** argv, char** envp) {
// test listing keys
EXPECT(config.listKeysForSpecialCategory("special")[1], "b");
// test anonymous
EXPECT(config.listKeysForSpecialCategory("specialAnonymous").size(), 2);
const auto KEYS = config.listKeysForSpecialCategory("specialAnonymous");
EXPECT(std::any_cast<int64_t>(config.getSpecialConfigValue("specialAnonymous", "value", KEYS[1].c_str())), 3);
// test sourcing
std::cout << " → Testing sourcing\n";
EXPECT(std::any_cast<int64_t>(config.getConfigValue("myColors:pink")), (Hyprlang::INT)0xFFc800c8);