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 don't pop up an error if the config value is missing
*/ */
bool ignoreMissing = false; 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

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

View file

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

View file

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

View file

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