mirror of
https://github.com/hyprwm/hyprlang.git
synced 2024-12-23 10:29:49 +01:00
Add support for multi-line configs
This commit is contained in:
parent
f054f2e44d
commit
2c5093321f
4 changed files with 82 additions and 12 deletions
|
@ -695,22 +695,52 @@ CParseResult CConfig::parse() {
|
||||||
CParseResult CConfig::parseRawStream(const std::string& stream) {
|
CParseResult CConfig::parseRawStream(const std::string& stream) {
|
||||||
CParseResult result;
|
CParseResult result;
|
||||||
|
|
||||||
|
std::string rawLine = "";
|
||||||
|
int rawLineNum = 0;
|
||||||
std::string line = "";
|
std::string line = "";
|
||||||
int linenum = 1;
|
int lineNum = 0;
|
||||||
|
|
||||||
std::stringstream str(stream);
|
std::stringstream str(stream);
|
||||||
|
|
||||||
while (std::getline(str, line)) {
|
while (std::getline(str, rawLine)) {
|
||||||
|
line = rawLine;
|
||||||
|
lineNum = ++rawLineNum;
|
||||||
|
|
||||||
|
bool mergeWithNextLine = rawLine.length() > 0 && rawLine.at(rawLine.length() - 1) == '\\';
|
||||||
|
bool gotWholeLine = true;
|
||||||
|
|
||||||
|
while (mergeWithNextLine) {
|
||||||
|
const auto lastNonSpace = line.length() < 2 ? -1 : line.find_last_not_of(MULTILINE_SPACE_CHARSET, line.length() - 2);
|
||||||
|
line = line.substr(0, lastNonSpace + 1);
|
||||||
|
|
||||||
|
if (!std::getline(str, rawLine)) {
|
||||||
|
if (!impl->parseError.empty())
|
||||||
|
impl->parseError += "\n";
|
||||||
|
impl->parseError += "Config error: Last line ends with backslash";
|
||||||
|
result.setError(impl->parseError);
|
||||||
|
gotWholeLine = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++rawLineNum;
|
||||||
|
line += rawLine;
|
||||||
|
mergeWithNextLine = line.length() > 0 && line.at(line.length() - 1) == '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gotWholeLine)
|
||||||
|
break;
|
||||||
|
|
||||||
const auto RET = parseLine(line);
|
const auto RET = parseLine(line);
|
||||||
|
|
||||||
if (RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
|
if (RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
|
||||||
if (!impl->parseError.empty())
|
if (!impl->parseError.empty())
|
||||||
impl->parseError += "\n";
|
impl->parseError += "\n";
|
||||||
impl->parseError += std::format("Config error at line {}: {}", linenum, RET.errorStdString);
|
impl->parseError += std::format("Config error at line {}: {}", lineNum, RET.errorStdString);
|
||||||
result.setError(impl->parseError);
|
result.setError(impl->parseError);
|
||||||
}
|
}
|
||||||
|
|
||||||
++linenum;
|
lineNum = rawLineNum + 1;
|
||||||
|
line = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!impl->categories.empty()) {
|
if (!impl->categories.empty()) {
|
||||||
|
@ -736,21 +766,50 @@ CParseResult CConfig::parseFile(const char* file) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string rawLine = "";
|
||||||
|
int rawLineNum = 0;
|
||||||
std::string line = "";
|
std::string line = "";
|
||||||
int linenum = 1;
|
int lineNum = 0;
|
||||||
|
|
||||||
while (std::getline(iffile, line)) {
|
while (std::getline(iffile, rawLine)) {
|
||||||
|
line = rawLine;
|
||||||
|
lineNum = ++rawLineNum;
|
||||||
|
|
||||||
|
bool mergeWithNextLine = rawLine.length() > 0 && rawLine.at(rawLine.length() - 1) == '\\';
|
||||||
|
bool gotWholeLine = true;
|
||||||
|
|
||||||
|
while (mergeWithNextLine) {
|
||||||
|
const auto lastNonSpace = line.length() < 2 ? -1 : line.find_last_not_of(MULTILINE_SPACE_CHARSET, line.length() - 2);
|
||||||
|
line = line.substr(0, lastNonSpace + 1);
|
||||||
|
|
||||||
|
if (!std::getline(iffile, rawLine)) {
|
||||||
|
if (!impl->parseError.empty())
|
||||||
|
impl->parseError += "\n";
|
||||||
|
impl->parseError += std::format("Config error in file {}: Last line ends with backslash", file);
|
||||||
|
result.setError(impl->parseError);
|
||||||
|
gotWholeLine = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++rawLineNum;
|
||||||
|
line += rawLine;
|
||||||
|
mergeWithNextLine = line.length() > 0 && line.at(line.length() - 1) == '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gotWholeLine)
|
||||||
|
break;
|
||||||
|
|
||||||
const auto RET = parseLine(line);
|
const auto RET = parseLine(line);
|
||||||
|
|
||||||
if (!impl->currentFlags.noError && RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
|
if (!impl->currentFlags.noError && RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) {
|
||||||
if (!impl->parseError.empty())
|
if (!impl->parseError.empty())
|
||||||
impl->parseError += "\n";
|
impl->parseError += "\n";
|
||||||
impl->parseError += std::format("Config error in file {} at line {}: {}", file, linenum, RET.errorStdString);
|
impl->parseError += std::format("Config error in file {} at line {}: {}", file, lineNum, RET.errorStdString);
|
||||||
result.setError(impl->parseError);
|
result.setError(impl->parseError);
|
||||||
}
|
}
|
||||||
|
|
||||||
++linenum;
|
lineNum = rawLineNum + 1;
|
||||||
|
line = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
iffile.close();
|
iffile.close();
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
static const char* MULTILINE_SPACE_CHARSET = " \t";
|
||||||
|
|
||||||
struct SHandler {
|
struct SHandler {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
Hyprlang::SHandlerOptions options;
|
Hyprlang::SHandlerOptions options;
|
||||||
|
|
|
@ -90,6 +90,11 @@ flagsStuff {
|
||||||
value = 2
|
value = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multiline = \
|
||||||
|
very \
|
||||||
|
long \
|
||||||
|
command
|
||||||
|
|
||||||
testCategory:testValueHex = 0xFFfFaAbB
|
testCategory:testValueHex = 0xFFfFaAbB
|
||||||
|
|
||||||
$RECURSIVE1 = a
|
$RECURSIVE1 = a
|
||||||
|
@ -103,4 +108,3 @@ doABarrelRoll = woohoo, some, params # Funny!
|
||||||
flagsabc = test
|
flagsabc = test
|
||||||
#doSomethingFunny = 1, 2, 3, 4 # Funnier!
|
#doSomethingFunny = 1, 2, 3, 4 # Funnier!
|
||||||
#testSpaces = abc , def # many spaces, should be trimmed
|
#testSpaces = abc , def # many spaces, should be trimmed
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,8 @@ int main(int argc, char** argv, char** envp) {
|
||||||
config.addSpecialCategory("specialAnonymous", {nullptr, false, true});
|
config.addSpecialCategory("specialAnonymous", {nullptr, false, true});
|
||||||
config.addSpecialConfigValue("specialAnonymous", "value", (Hyprlang::INT)0);
|
config.addSpecialConfigValue("specialAnonymous", "value", (Hyprlang::INT)0);
|
||||||
|
|
||||||
|
config.addConfigValue("multiline", "");
|
||||||
|
|
||||||
config.commence();
|
config.commence();
|
||||||
|
|
||||||
config.addSpecialCategory("specialGeneric:one", {nullptr, true});
|
config.addSpecialCategory("specialGeneric:one", {nullptr, true});
|
||||||
|
@ -269,6 +271,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
std::cout << " → Testing custom types\n";
|
std::cout << " → Testing custom types\n";
|
||||||
EXPECT(*reinterpret_cast<int64_t*>(std::any_cast<void*>(config.getConfigValue("customType"))), (Hyprlang::INT)1);
|
EXPECT(*reinterpret_cast<int64_t*>(std::any_cast<void*>(config.getConfigValue("customType"))), (Hyprlang::INT)1);
|
||||||
|
|
||||||
|
// test multiline config
|
||||||
|
EXPECT(std::any_cast<const char*>(config.getConfigValue("multiline")), std::string{"very long command"});
|
||||||
|
|
||||||
std::cout << " → Testing error.conf\n";
|
std::cout << " → Testing error.conf\n";
|
||||||
Hyprlang::CConfig errorConfig("./config/error.conf", {.verifyOnly = true, .throwAllErrors = true});
|
Hyprlang::CConfig errorConfig("./config/error.conf", {.verifyOnly = true, .throwAllErrors = true});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue