Skip to content

Commit

Permalink
API: add anonymous special categories
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Feb 17, 2024
1 parent 65a7f87 commit 378c3e2
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 10 deletions.
11 changes: 11 additions & 0 deletions include/hyprlang.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/*!
Expand Down
41 changes: 31 additions & 10 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
#include <expected>

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) {
if (str.empty())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -310,13 +317,27 @@ CParseResult CConfig::configSetValueSafe(const std::string& command, const std::
if (VALUEIT != PCAT->values.end())
found = true;

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;
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;
}

impl->currentSpecialKey = value;

break;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct SSpecialCategoryDescriptor {
std::string key = "";
std::unordered_map<std::string, SConfigDefaultValue> defaultValues;
bool dontErrorOnMissing = false;
bool anonymous = false;
};

struct SSpecialCategory {
Expand All @@ -51,6 +52,9 @@ struct SSpecialCategory {
bool isStatic = false;

void applyDefaults();

// for easy anonymous ID'ing
size_t anonymousID = 0;
};

class CConfigImpl {
Expand Down
8 changes: 8 additions & 0 deletions tests/config/config.conf
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ specialGeneric {
}
}

specialAnonymous {
value = 2
}

specialAnonymous {
value = 3
}

testCategory:testValueHex = 0xFFfFaAbB

testStringQuotes = "Hello World!"
Expand Down
8 changes: 8 additions & 0 deletions tests/parse/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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});
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 378c3e2

Please sign in to comment.