mirror of
https://github.com/hyprwm/hyprlang.git
synced 2024-12-22 09:59:48 +01:00
core: add options for config parser
This commit is contained in:
parent
c69c286b31
commit
70145fd8da
5 changed files with 46 additions and 8 deletions
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -69,4 +69,6 @@ class CConfigImpl {
|
|||
std::string currentSpecialKey = "";
|
||||
|
||||
std::string parseError = "";
|
||||
|
||||
Hyprlang::SConfigOptions configOptions;
|
||||
};
|
6
tests/config/error.conf
Normal file
6
tests/config/error.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
# This config houses two errors
|
||||
|
||||
someValue = 123
|
||||
|
||||
category {
|
||||
invalid_line
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue