core: add options for config parser

This commit is contained in:
Vaxry 2023-12-30 13:30:46 +01:00
parent c69c286b31
commit 70145fd8da
5 changed files with 46 additions and 8 deletions

View file

@ -50,6 +50,15 @@ namespace Hyprlang {
friend class CConfig;
};
/* Generic struct for options for the config parser */
struct SConfigOptions {
/* Don't throw errors on missing values. */
bool verifyOnly = false;
/* Return all errors instead of the first */
bool throwAllErrors = false;
};
/* Generic struct for options for handlers */
struct SHandlerOptions {
bool allowFlags = false;
@ -142,7 +151,7 @@ namespace Hyprlang {
/* Base class for a config file */
class CConfig {
public:
CConfig(const char* configPath);
CConfig(const char* configPath, const SConfigOptions& options);
~CConfig();
/* Add a config value, for example myCategory:myValue.

View file

@ -28,7 +28,7 @@ static std::string removeBeginEndSpacesTabs(std::string str) {
return str;
}
CConfig::CConfig(const char* path) {
CConfig::CConfig(const char* path, const Hyprlang::SConfigOptions& options) {
impl = new CConfigImpl;
try {
impl->path = std::filesystem::canonical(path);
@ -46,6 +46,8 @@ CConfig::CConfig(const char* path) {
}
std::sort(impl->envVariables.begin(), impl->envVariables.end(), [&](const auto& a, const auto& b) { return a.name.length() > b.name.length(); });
impl->configOptions = options;
}
CConfig::~CConfig() {
@ -444,7 +446,7 @@ CParseResult CConfig::parseLine(std::string line, bool dynamic) {
found = true;
}
if (!found)
if (!found && !impl->configOptions.verifyOnly)
ret = configSetValueSafe(LHS, RHS);
if (ret.error)
@ -515,9 +517,11 @@ CParseResult CConfig::parseFile(std::string file) {
const auto RET = parseLine(line);
if (RET.error && impl->parseError.empty()) {
impl->parseError = RET.getError();
result.setError(std::format("Config error in file {} at line {}: {}", file, linenum, RET.errorStdString));
if (RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
if (!impl->parseError.empty())
impl->parseError += "\n";
impl->parseError += std::format("Config error in file {} at line {}: {}", file, linenum, RET.errorStdString);
result.setError(impl->parseError);
}
++linenum;
@ -526,7 +530,13 @@ CParseResult CConfig::parseFile(std::string file) {
iffile.close();
if (!impl->categories.empty()) {
result.setError("Unclosed category at EOF");
if (impl->parseError.empty() || impl->configOptions.throwAllErrors) {
if (!impl->parseError.empty())
impl->parseError += "\n";
impl->parseError += std::format("Config error in file {}: Unclosed category at EOF", file);
result.setError(impl->parseError);
}
impl->categories.clear();
}

View file

@ -69,4 +69,6 @@ class CConfigImpl {
std::string currentSpecialKey = "";
std::string parseError = "";
Hyprlang::SConfigOptions configOptions;
};

6
tests/config/error.conf Normal file
View file

@ -0,0 +1,6 @@
# This config houses two errors
someValue = 123
category {
invalid_line

View file

@ -1,5 +1,6 @@
#include <iostream>
#include <filesystem>
#include <algorithm>
#include <hyprlang.hpp>
@ -75,7 +76,7 @@ int main(int argc, char** argv, char** envp) {
std::cout << "Starting test\n";
Hyprlang::CConfig config("./config/config.conf");
Hyprlang::CConfig config("./config/config.conf", {});
pConfig = &config;
currentPath = std::filesystem::canonical("./config/");
@ -182,6 +183,16 @@ int main(int argc, char** argv, char** envp) {
std::cout << " → Testing custom types\n";
EXPECT(*reinterpret_cast<int64_t*>(std::any_cast<void*>(config.getConfigValue("customType"))), 1L);
std::cout << " → Testing error.conf\n";
Hyprlang::CConfig errorConfig("./config/error.conf", {.verifyOnly = true, .throwAllErrors = true});
errorConfig.commence();
const auto ERRORS = errorConfig.parse();
EXPECT(ERRORS.error, true);
const auto ERRORSTR = std::string{ERRORS.getError()};
EXPECT(std::count(ERRORSTR.begin(), ERRORSTR.end(), '\n'), 1);
} catch (const char* e) {
std::cout << Colors::RED << "Error: " << Colors::RESET << e << "\n";
return 1;