Do not fail to parse a multi-bar config

This commit is contained in:
tiosgz 2021-07-10 20:22:37 +00:00
parent 7c1303f57c
commit 78aaa5c1b4
3 changed files with 41 additions and 11 deletions

View File

@ -39,6 +39,7 @@ class Client {
void handleOutput(struct waybar_output &output); void handleOutput(struct waybar_output &output);
bool isValidOutput(const Json::Value &config, struct waybar_output &output); bool isValidOutput(const Json::Value &config, struct waybar_output &output);
auto setupConfig(const std::string &config_file, int depth) -> void; auto setupConfig(const std::string &config_file, int depth) -> void;
auto resolveConfigIncludes(Json::Value &config, int depth) -> void;
auto mergeConfig(Json::Value &a_config_, Json::Value &b_config_) -> void; auto mergeConfig(Json::Value &a_config_, Json::Value &b_config_) -> void;
auto setupCss(const std::string &css_file) -> void; auto setupCss(const std::string &css_file) -> void;
struct waybar_output & getOutput(void *); struct waybar_output & getOutput(void *);

View File

@ -86,8 +86,9 @@ Also a minimal example configuration can be found on the at the bottom of this m
Only functional if compiled with gtk-layer-shell support. Only functional if compiled with gtk-layer-shell support.
*include* ++ *include* ++
typeof: array ++ typeof: string|array ++
Paths to additional configuration files. In case of duplicate options, the including file's value takes precedence. Make sure to avoid circular imports. Paths to additional configuration files. In case of duplicate options, the including file's value takes precedence. Make sure to avoid circular imports.
For a multi-bar config, specify at least an empty object for each bar also in every file being included.
# MODULE FORMAT # MODULE FORMAT

View File

@ -245,22 +245,50 @@ auto waybar::Client::setupConfig(const std::string &config_file, int depth) -> v
std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
util::JsonParser parser; util::JsonParser parser;
Json::Value tmp_config_ = parser.parse(str); Json::Value tmp_config_ = parser.parse(str);
if (tmp_config_["include"].isArray()) { if (tmp_config_.isArray()) {
for (const auto &include : tmp_config_["include"]) { for (auto &config_part : tmp_config_) {
spdlog::info("Including resource file: {}", include.asString()); resolveConfigIncludes(config_part, depth);
setupConfig(getValidPath({include.asString()}), ++depth);
} }
} else {
resolveConfigIncludes(tmp_config_, depth);
} }
mergeConfig(config_, tmp_config_); mergeConfig(config_, tmp_config_);
} }
auto waybar::Client::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) -> void { auto waybar::Client::resolveConfigIncludes(Json::Value &config, int depth) -> void {
for (const auto &key : b_config_.getMemberNames()) { Json::Value includes = config["include"];
if (a_config_[key].type() == Json::objectValue && b_config_[key].type() == Json::objectValue) { if (includes.isArray()) {
mergeConfig(a_config_[key], b_config_[key]); for (const auto &include : includes) {
} else { spdlog::info("Including resource file: {}", include.asString());
a_config_[key] = b_config_[key]; setupConfig(getValidPath({include.asString()}), ++depth);
} }
} else if (includes.isString()) {
spdlog::info("Including resource file: {}", includes.asString());
setupConfig(getValidPath({includes.asString()}), ++depth);
}
}
auto waybar::Client::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) -> void {
if (!a_config_) {
// For the first config
a_config_ = b_config_;
} else if (a_config_.isObject() && b_config_.isObject()) {
for (const auto &key : b_config_.getMemberNames()) {
if (a_config_[key].isObject() && b_config_[key].isObject()) {
mergeConfig(a_config_[key], b_config_[key]);
} else {
a_config_[key] = b_config_[key];
}
}
} else if (a_config_.isArray() && b_config_.isArray()) {
// This can happen only on the top-level array of a multi-bar config
for (Json::Value::ArrayIndex i = 0; i < b_config_.size(); i++) {
if (a_config_[i].isObject() && b_config_[i].isObject()) {
mergeConfig(a_config_[i], b_config_[i]);
}
}
} else {
spdlog::error("Cannot merge config, conflicting or invalid JSON types");
} }
} }