diff --git a/src/VarList.cpp b/src/VarList.cpp new file mode 100644 index 0000000..518acde --- /dev/null +++ b/src/VarList.cpp @@ -0,0 +1,55 @@ +#include "VarList.hpp" +#include +#include + +static std::string removeBeginEndSpacesTabs(std::string str) { + if (str.empty()) + return str; + + int countBefore = 0; + while (str[countBefore] == ' ' || str[countBefore] == '\t') { + countBefore++; + } + + int countAfter = 0; + while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) { + countAfter++; + } + + str = str.substr(countBefore, str.length() - countBefore - countAfter); + + return str; +} + +CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) { + if (in.empty()) + m_vArgs.emplace_back(""); + + std::string args{in}; + size_t idx = 0; + size_t pos = 0; + std::ranges::replace_if( + args, [&](const char& c) { return delim == 's' ? std::isspace(c) : c == delim; }, 0); + + for (const auto& s : args | std::views::split(0)) { + if (removeEmpty && s.empty()) + continue; + if (++idx == lastArgNo) { + m_vArgs.emplace_back(removeBeginEndSpacesTabs(in.substr(pos))); + break; + } + pos += s.size() + 1; + m_vArgs.emplace_back(removeBeginEndSpacesTabs(std::string_view{s}.data())); + } +} + +std::string CVarList::join(const std::string& joiner, size_t from, size_t to) const { + size_t last = to == 0 ? size() : to; + + std::string rolling; + for (size_t i = from; i < last; ++i) { + rolling += m_vArgs[i] + (i + 1 < last ? joiner : ""); + } + + return rolling; +} \ No newline at end of file diff --git a/src/VarList.hpp b/src/VarList.hpp new file mode 100644 index 0000000..1374da6 --- /dev/null +++ b/src/VarList.hpp @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include + +class CVarList { + public: + /** Split string into arg list + @param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args + @param delim if delimiter is 's', use std::isspace + @param removeEmpty remove empty args from argv + */ + CVarList(const std::string& in, const size_t maxSize = 0, const char delim = ',', const bool removeEmpty = false); + + ~CVarList() = default; + + size_t size() const { + return m_vArgs.size(); + } + + std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const; + + void map(std::function func) { + for (auto& s : m_vArgs) + func(s); + } + + void append(const std::string arg) { + m_vArgs.emplace_back(arg); + } + + std::string operator[](const size_t& idx) const { + if (idx >= m_vArgs.size()) + return ""; + return m_vArgs[idx]; + } + + // for range-based loops + std::vector::iterator begin() { + return m_vArgs.begin(); + } + std::vector::const_iterator begin() const { + return m_vArgs.begin(); + } + std::vector::iterator end() { + return m_vArgs.end(); + } + std::vector::const_iterator end() const { + return m_vArgs.end(); + } + + bool contains(const std::string& el) { + for (auto& a : m_vArgs) { + if (a == el) + return true; + } + + return false; + } + + private: + std::vector m_vArgs; +}; \ No newline at end of file diff --git a/src/config.cpp b/src/config.cpp index ecefe52..bee4e64 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -9,6 +9,8 @@ #include #include +#include "VarList.hpp" + using namespace Hyprlang; #ifdef __APPLE__ @@ -510,6 +512,18 @@ CParseResult CConfig::parseVariable(const std::string& lhs, const std::string& r return result; } +void CConfigImpl::parseComment(const std::string& comment) { + const auto COMMENT = removeBeginEndSpacesTabs(comment); + + if (!COMMENT.starts_with("hyprlang")) + return; + + CVarList args(COMMENT, 0, 's', true); + + if (args[1] == "noerror") + currentFlags.noError = args[2] == "true" || args[2] == "yes" || args[2] == "enable" || args[2] == "enabled" || args[2] == "set"; +} + CParseResult CConfig::parseLine(std::string line, bool dynamic) { CParseResult result; @@ -517,8 +531,10 @@ CParseResult CConfig::parseLine(std::string line, bool dynamic) { auto commentPos = line.find('#'); - if (commentPos == 0) + if (commentPos == 0) { + impl->parseComment(line.substr(1)); return result; + } size_t lastHashPos = 0; @@ -737,7 +753,7 @@ CParseResult CConfig::parseFile(const char* file) { const auto RET = parseLine(line); - if (RET.error && (impl->parseError.empty() || impl->configOptions.throwAllErrors)) { + if (!impl->currentFlags.noError && 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); diff --git a/src/config.hpp b/src/config.hpp index 80d21b1..54674a1 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -87,4 +87,10 @@ class CConfigImpl { std::string parseError = ""; Hyprlang::SConfigOptions configOptions; + + void parseComment(const std::string& comment); + + struct { + bool noError = false; + } currentFlags; }; \ No newline at end of file diff --git a/tests/config/config.conf b/tests/config/config.conf index 243421c..1feedd1 100644 --- a/tests/config/config.conf +++ b/tests/config/config.conf @@ -22,6 +22,12 @@ customType = abc testStringColon = ee:ee:ee +# hyprlang noerror true + +errorVariable = true + +# hyprlang noerror false + testCategory { testValueInt = 123456 testValueHex = 0xF