From eb311838538b80fb3280aa9ab5b57abc22925926 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sat, 9 Nov 2019 21:05:07 +0200 Subject: Add configuration subcommand --dump: Write current configuration to stdout and exit --- lib/configuration/configuration.cpp | 44 ++++++++++++++++++++++++-------- lib/configuration/configuration.h | 51 +++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index bd7700c..34e84af 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -7,11 +7,11 @@ */ #include "configuration.h" -#include +#include #include -#include #include -#include +#include +#include static std::unique_ptr s_conf; @@ -21,7 +21,6 @@ inline void strip(std::string &value) value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to(), ' ')).base(), value.end()); } - Configuration::Configuration() : use_global(true) { @@ -32,9 +31,9 @@ Configuration::Configuration() Configuration::Configuration(std::initializer_list> l) noexcept : m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()) { - for(const auto &i : l) { - insert_or_assign(i.first, i.second); - } + for(const auto &i : l) { + insert_or_assign(i.first, i.second); + } } void Configuration::read(std::basic_istream &input) @@ -69,18 +68,16 @@ void Configuration::read(std::basic_istream &input) } else if(std::holds_alternative(v)) { at(key) = (value == "true"); } - } } } - void Configuration::move_global(std::unique_ptr &&conf) { s_conf = std::move(conf); } -Configuration* Configuration::instance() +Configuration *Configuration::instance() { return s_conf.get(); } @@ -101,3 +98,30 @@ void setShortcut(QAction *action, const char *name) } #endif } + +std::ostream &operator<<(std::ostream &out, const Configuration &obj) +{ + // unordered_map is, well, unordered, so grab the keys and sort them before printing them + std::vector keys; + + if(obj.use_global) { + if(!s_conf) + throw new std::runtime_error("Trying to use default Configuration, but none has been set!"); + + for(const auto &pair : *s_conf) + keys.emplace_back(pair.first); + } else { + for(const auto &pair : obj) + out << pair.first << "\n"; + } + std::sort(keys.begin(), keys.end()); + + for(const auto &key : keys) { + if(obj.use_global) + out << key << "=" << s_conf->value(key.c_str()).value() << "\n"; + else + out << key << "=" << obj.value(key.c_str()).value() << "\n"; + } + + return out; +} diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h index b77685a..4459dd0 100644 --- a/lib/configuration/configuration.h +++ b/lib/configuration/configuration.h @@ -9,21 +9,21 @@ #ifndef SMOLBOTE_CONFIGURATION_H #define SMOLBOTE_CONFIGURATION_H +#include +#include +#include +#include #include #include -#include #include #include -#include -#include -#include -#include +#include -#if defined (__clang__) -#define consumable(X) [[clang::consumable(X)]] -#define return_typestate(X) [[clang::return_typestate(X)]] -#define callable_when(X) [[clang::callable_when(X)]] -#define param_typestate(X) [[clang::param_typestate(X)]] +#if defined(__clang__) +#define consumable(X) [[clang::consumable(X)]] +#define return_typestate(X) [[clang::return_typestate(X)]] +#define callable_when(X) [[clang::callable_when(X)]] +#define param_typestate(X) [[clang::param_typestate(X)]] #else #define consumable(X) #define return_typestate(X) @@ -35,27 +35,25 @@ typedef std::variant conf_value_t; class consumable(unconsumed) Configuration : private std::unordered_map { + friend std::ostream &operator<<(std::ostream &out, const Configuration &obj); public: - return_typestate(unconsumed) - explicit Configuration(); + return_typestate(unconsumed) explicit Configuration(); - return_typestate(unconsumed) - explicit Configuration(std::initializer_list> l) noexcept; + return_typestate(unconsumed) explicit Configuration(std::initializer_list> l) noexcept; - explicit Configuration(Configuration &&other param_typestate(unconsumed)) = default; + explicit Configuration(Configuration && other param_typestate(unconsumed)) = default; ~Configuration() = default; - callable_when(unconsumed) - void read(std::basic_istream &input); + callable_when(unconsumed) void read(std::basic_istream & input); template callable_when(unconsumed) std::optional value(const char *path) const { if(use_global) return instance()->value(path); - + if(this->count(path) == 0) { return std::nullopt; } @@ -64,7 +62,15 @@ public: const auto value = at(path); if constexpr(std::is_same_v || std::is_same_v) { - auto r = std::get(value); + auto r = [&value]() { + if(std::holds_alternative(value)) + return std::get(value); + else if(std::holds_alternative(value)) + return std::to_string(std::get(value)); + else + return std::get(value) ? std::string("true") : std::string("false"); + }(); + if(r.front() == '~') r.replace(0, 1, m_homePath); @@ -76,14 +82,14 @@ public: } else if constexpr(std::is_same_v) { return std::make_optional(QString::fromStdString(std::get(value)).split(';')); - } else if (std::holds_alternative(value)) { + } else if(std::holds_alternative(value)) { return std::optional(std::get(value)); } else return std::nullopt; - + } // std::optional value(path) const - static void move_global(std::unique_ptr &&conf); + static void move_global(std::unique_ptr && conf); private: static Configuration *instance(); @@ -93,5 +99,6 @@ private: }; void setShortcut(QAction *action, const char *name); +std::ostream &operator<<(std::ostream &out, const Configuration &obj); #endif // SMOLBOTE_CONFIGURATION_H -- cgit v1.2.1