API: add pathIsStream to SConfigOptions

This commit is contained in:
Vaxry 2024-03-07 18:14:02 +00:00
parent f1db1a7e1f
commit 66c099e097
3 changed files with 74 additions and 17 deletions

View file

@ -107,6 +107,13 @@ namespace Hyprlang {
Don't throw on a missing config file. Carry on as if nothing happened. Don't throw on a missing config file. Carry on as if nothing happened.
*/ */
bool allowMissingConfig = false; bool allowMissingConfig = false;
/*!
\since 0.4.2
Treat configPath as a raw config stream.
*/
bool pathIsStream = false;
}; };
/*! /*!
@ -429,6 +436,7 @@ namespace Hyprlang {
void clearState(); void clearState();
void applyDefaultsToCat(SSpecialCategory& cat); void applyDefaultsToCat(SSpecialCategory& cat);
void retrieveKeysForCat(const char* category, const char*** out, size_t* len); void retrieveKeysForCat(const char* category, const char*** out, size_t* len);
CParseResult parseRawStream(const std::string& stream);
}; };
}; };
#endif #endif

View file

@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <expected> #include <expected>
#include <sstream>
using namespace Hyprlang; using namespace Hyprlang;
extern "C" char** environ; extern "C" char** environ;
@ -34,10 +35,14 @@ static std::string removeBeginEndSpacesTabs(std::string str) {
} }
CConfig::CConfig(const char* path, const Hyprlang::SConfigOptions& options) { CConfig::CConfig(const char* path, const Hyprlang::SConfigOptions& options) {
impl = new CConfigImpl; impl = new CConfigImpl;
impl->path = path;
if (!std::filesystem::exists(impl->path)) { if (options.pathIsStream)
impl->rawConfigString = path;
else
impl->path = path;
if (!options.pathIsStream && !std::filesystem::exists(impl->path)) {
if (!options.allowMissingConfig) if (!options.allowMissingConfig)
throw "File does not exist"; throw "File does not exist";
} }
@ -593,24 +598,65 @@ CParseResult CConfig::parse() {
applyDefaultsToCat(*sc); applyDefaultsToCat(*sc);
} }
bool fileExists = std::filesystem::exists(impl->path); CParseResult fileParseResult;
// implies options.allowMissingConfig if (impl->rawConfigString.empty()) {
if (impl->configOptions.allowMissingConfig && !fileExists) bool fileExists = std::filesystem::exists(impl->path);
return CParseResult{};
else if (!fileExists) { // implies options.allowMissingConfig
CParseResult res; if (impl->configOptions.allowMissingConfig && !fileExists)
res.setError("Config file is missing"); return CParseResult{};
return res; else if (!fileExists) {
CParseResult res;
res.setError("Config file is missing");
return res;
}
std::string canonical = std::filesystem::canonical(impl->path);
fileParseResult = parseFile(canonical.c_str());
} else {
fileParseResult = parseRawStream(impl->rawConfigString);
} }
std::string canonical = std::filesystem::canonical(impl->path);
CParseResult fileParseResult = parseFile(canonical.c_str());
return fileParseResult; return fileParseResult;
} }
CParseResult CConfig::parseRawStream(const std::string& stream) {
CParseResult result;
std::string line = "";
int linenum = 1;
std::stringstream str(stream);
while (std::getline(str, line)) {
const auto RET = parseLine(line);
if (RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
if (!impl->parseError.empty())
impl->parseError += "\n";
impl->parseError += std::format("Config error at line {}: {}", linenum, RET.errorStdString);
result.setError(impl->parseError);
}
++linenum;
}
if (!impl->categories.empty()) {
if (impl->parseError.empty() || impl->configOptions.throwAllErrors) {
if (!impl->parseError.empty())
impl->parseError += "\n";
impl->parseError += std::format("Config error: Unclosed category at EOF");
result.setError(impl->parseError);
}
impl->categories.clear();
}
return result;
}
CParseResult CConfig::parseFile(const char* file) { CParseResult CConfig::parseFile(const char* file) {
CParseResult result; CParseResult result;

View file

@ -66,8 +66,11 @@ struct SSpecialCategory {
class CConfigImpl { class CConfigImpl {
public: public:
std::string path = ""; std::string path = "";
std::string originalPath = ""; std::string originalPath = "";
// if not-empty, used instead of path
std::string rawConfigString = "";
std::unordered_map<std::string, Hyprlang::CConfigValue> values; std::unordered_map<std::string, Hyprlang::CConfigValue> values;
std::unordered_map<std::string, SConfigDefaultValue> defaultValues; std::unordered_map<std::string, SConfigDefaultValue> defaultValues;