refactor(config): Cleanup and minor tweaks

This commit is contained in:
Michael Carlberg 2016-12-14 05:12:15 +01:00
parent 060d198b8e
commit 80a00bd596
8 changed files with 116 additions and 83 deletions

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "components/config.hpp"
#include "components/screen.hpp" #include "components/screen.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "errors.hpp" #include "errors.hpp"

View File

@ -31,16 +31,14 @@ class config {
explicit config(const logger& logger, const xresource_manager& xrm, string&& path = "", string&& bar = ""); explicit config(const logger& logger, const xresource_manager& xrm, string&& path = "", string&& bar = "");
void load(string file, string barname);
string filepath() const; string filepath() const;
string bar_section() const; string section() const;
vector<string> defined_bars() const;
void warn_deprecated(const string& section, const string& key, string replacement) const; void warn_deprecated(const string& section, const string& key, string replacement) const;
/** /**
* Returns true if a given parameter exists * Returns true if a given parameter exists
*/ */
template <typename T>
bool has(const string& section, const string& key) const { bool has(const string& section, const string& key) const {
auto it = m_sections.find(section); auto it = m_sections.find(section);
return it != m_sections.end() && it->second.find(key) != it->second.end(); return it != m_sections.end() && it->second.find(key) != it->second.end();
@ -51,7 +49,7 @@ class config {
*/ */
template <typename T> template <typename T>
T get(const string& key) const { T get(const string& key) const {
return get<T>(bar_section(), key); return get<T>(section(), key);
} }
/** /**
@ -100,7 +98,7 @@ class config {
*/ */
template <typename T> template <typename T>
vector<T> get_list(const string& key) const { vector<T> get_list(const string& key) const {
return get_list<T>(bar_section(), key); return get_list<T>(section(), key);
} }
/** /**
@ -152,8 +150,38 @@ class config {
return vec; return vec;
} }
/**
* Attempt to load value using the deprecated key name. If successful show a
* warning message. If it fails load the value using the new key and given
* fallback value
*/
template <typename T>
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
try {
T value{get<T>(section, old)};
warn_deprecated(section, old, newkey);
return value;
} catch (const key_error& err) {
return get<T>(section, newkey, fallback);
}
}
/**
* @see deprecated<T>
*/
template <typename T>
T deprecated_list(const string& section, const string& old, const string& newkey, const vector<T>& fallback) const {
try {
vector<T> value{get_list<T>(section, old)};
warn_deprecated(section, old, newkey);
return value;
} catch (const key_error& err) {
return get_list<T>(section, newkey, fallback);
}
}
protected: protected:
void read(); void parse_file();
void copy_inherited(); void copy_inherited();
template <typename T> template <typename T>
@ -206,8 +234,8 @@ class config {
m_logger.warn("${BAR.key} is deprecated. Use ${root.key} instead"); m_logger.warn("${BAR.key} is deprecated. Use ${root.key} instead");
} }
section = string_util::replace(section, "BAR", bar_section(), 0, 3); section = string_util::replace(section, "BAR", this->section(), 0, 3);
section = string_util::replace(section, "root", bar_section(), 0, 4); section = string_util::replace(section, "root", this->section(), 0, 4);
section = string_util::replace(section, "self", current_section, 0, 4); section = string_util::replace(section, "self", current_section, 0, 4);
optional<T> result{opt<T>(section, key)}; optional<T> result{opt<T>(section, key)};
@ -263,7 +291,7 @@ class config {
const logger& m_logger; const logger& m_logger;
const xresource_manager& m_xrm; const xresource_manager& m_xrm;
string m_file; string m_file;
string m_current_bar; string m_barname;
sectionmap_t m_sections; sectionmap_t m_sections;
}; };

View File

@ -24,7 +24,7 @@ namespace modules {
#define DEFINE_UNSUPPORTED_MODULE(MODULE_NAME, MODULE_TYPE) \ #define DEFINE_UNSUPPORTED_MODULE(MODULE_NAME, MODULE_TYPE) \
class MODULE_NAME : public module_interface { \ class MODULE_NAME : public module_interface { \
public: \ public: \
MODULE_NAME(const bar_settings, const logger&, const config&, string) { \ MODULE_NAME(const bar_settings, string) { \
throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \ throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \
} \ } \
string name() const { \ string name() const { \

View File

@ -3,9 +3,7 @@
#include <string> #include <string>
#include "components/bar.hpp" #include "components/bar.hpp"
#include "components/command_line.hpp"
#include "components/config.hpp" #include "components/config.hpp"
#include "components/eventloop.hpp"
#include "components/parser.hpp" #include "components/parser.hpp"
#include "components/renderer.hpp" #include "components/renderer.hpp"
#include "components/screen.hpp" #include "components/screen.hpp"
@ -60,7 +58,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
, m_log(logger) , m_log(logger)
, m_screen(move(screen)) , m_screen(move(screen))
, m_tray(move(tray_manager)) { , m_tray(move(tray_manager)) {
string bs{m_conf.bar_section()}; string bs{m_conf.section()};
// Get available RandR outputs // Get available RandR outputs
auto monitor_name = m_conf.get<string>(bs, "monitor", ""); auto monitor_name = m_conf.get<string>(bs, "monitor", "");
@ -163,10 +161,10 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
m_opts.borders[edge::RIGHT].color = color::parse(m_conf.get<string>(bs, "border-right-color", bcolor)); m_opts.borders[edge::RIGHT].color = color::parse(m_conf.get<string>(bs, "border-right-color", bcolor));
// Load geometry values // Load geometry values
auto w = m_conf.get<string>(m_conf.bar_section(), "width", "100%"); auto w = m_conf.get<string>(m_conf.section(), "width", "100%");
auto h = m_conf.get<string>(m_conf.bar_section(), "height", "24"); auto h = m_conf.get<string>(m_conf.section(), "height", "24");
auto offsetx = m_conf.get<string>(m_conf.bar_section(), "offset-x", ""); auto offsetx = m_conf.get<string>(m_conf.section(), "offset-x", "");
auto offsety = m_conf.get<string>(m_conf.bar_section(), "offset-y", ""); auto offsety = m_conf.get<string>(m_conf.section(), "offset-y", "");
if ((m_opts.size.w = atoi(w.c_str())) && w.find('%') != string::npos) { if ((m_opts.size.w = atoi(w.c_str())) && w.find('%') != string::npos) {
m_opts.size.w = math_util::percentage_to_value<int>(m_opts.size.w, m_opts.monitor->w); m_opts.size.w = math_util::percentage_to_value<int>(m_opts.size.w, m_opts.monitor->w);
@ -211,7 +209,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
m_opts.center.x += m_opts.borders[edge::LEFT].size; m_opts.center.x += m_opts.borders[edge::LEFT].size;
m_log.trace("bar: Create renderer"); m_log.trace("bar: Create renderer");
auto fonts = m_conf.get_list<string>(m_conf.bar_section(), "font", {}); auto fonts = m_conf.get_list<string>(m_conf.section(), "font", {});
m_renderer = renderer::make(m_opts, move(fonts)); m_renderer = renderer::make(m_opts, move(fonts));
m_log.trace("bar: Attaching sink to registry"); m_log.trace("bar: Attaching sink to registry");
@ -312,7 +310,7 @@ void bar::restack_window() {
string wm_restack; string wm_restack;
try { try {
wm_restack = m_conf.get<string>(m_conf.bar_section(), "wm-restack"); wm_restack = m_conf.get<string>(m_conf.section(), "wm-restack");
} catch (const key_error& err) { } catch (const key_error& err) {
return; return;
} }

View File

@ -1,4 +1,5 @@
#include <algorithm> #include <algorithm>
#include <chrono>
#include <fstream> #include <fstream>
#include <istream> #include <istream>
#include <utility> #include <utility>
@ -7,59 +8,45 @@
#include "utils/env.hpp" #include "utils/env.hpp"
#include "utils/factory.hpp" #include "utils/factory.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
#include "utils/string.hpp"
POLYBAR_NS POLYBAR_NS
namespace chrono = std::chrono;
/** /**
* Create instance * Create instance
*/ */
config::make_type config::make(string path, string bar) { config::make_type config::make(string path, string bar) {
return static_cast<config::make_type>(*factory_util::singleton<std::remove_reference_t<config::make_type>>( return static_cast<config::make_type>(*factory_util::singleton<std::remove_reference_t<config::make_type>>(
*factory_util::singleton<const config>(logger::make(), xresource_manager::make(), move(path), move(bar)))); logger::make(), xresource_manager::make(), move(path), move(bar)));
} }
/** /**
* Construct config object * Construct config object
*/ */
config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar) config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar)
: m_logger(logger), m_xrm(xrm) { : m_logger(logger), m_xrm(xrm), m_file(forward<decltype(path)>(path)), m_barname(forward<decltype(bar)>(bar)) {
if (!path.empty() && !bar.empty()) { if (!file_util::exists(m_file)) {
load(forward<decltype(path)>(path), forward<decltype(bar)>(bar)); throw application_error("Could not find config file: " + m_file);
}
}
/**
* Load configuration and validate bar section
*
* This is done outside the constructor due to boost::di noexcept
*/
void config::load(string file, string barname) {
m_file = file;
m_current_bar = move(barname);
if (!file_util::exists(file)) {
throw application_error("Could not find config file: " + file);
} }
// Read values parse_file();
read();
auto bars = defined_bars(); bool found_bar{false};
if (std::find(bars.begin(), bars.end(), m_current_bar) == bars.end()) { for (auto&& p : m_sections) {
throw application_error("Undefined bar: " + m_current_bar); if (p.first == section()) {
found_bar = true;
break;
}
} }
if (env_util::has("XDG_CONFIG_HOME")) { if (!found_bar) {
file = string_util::replace(file, env_util::get("XDG_CONFIG_HOME"), "$XDG_CONFIG_HOME"); throw application_error("Undefined bar: " + m_barname);
}
if (env_util::has("HOME")) {
file = string_util::replace(file, env_util::get("HOME"), "~");
} }
m_logger.trace("config: Loaded %s", file); m_logger.trace("config: Loaded %s", m_file);
m_logger.trace("config: Current bar section: [%s]", bar_section()); m_logger.trace("config: Current bar section: [%s]", section());
copy_inherited();
} }
/** /**
@ -72,23 +59,8 @@ string config::filepath() const {
/** /**
* Get the section name of the bar in use * Get the section name of the bar in use
*/ */
string config::bar_section() const { string config::section() const {
return "bar/" + m_current_bar; return "bar/" + m_barname;
}
/**
* Get a list of defined bar sections in the current config
*/
vector<string> config::defined_bars() const {
vector<string> bars;
for (auto&& p : m_sections) {
if (p.first.compare(0, 4, "bar/") == 0) {
bars.emplace_back(p.first.substr(4));
}
}
return bars;
} }
/** /**
@ -102,13 +74,20 @@ void config::warn_deprecated(const string& section, const string& key, string re
} }
} }
void config::read() { /**
* Parse key/value pairs from the configuration file
*/
void config::parse_file() {
std::ifstream in(m_file.c_str()); std::ifstream in(m_file.c_str());
string line; string line;
string section; string section;
uint32_t lineno{0};
while (std::getline(in, line)) { while (std::getline(in, line)) {
if (line.empty()) { lineno++;
// Ignore empty lines and comments
if (line.empty() || line[0] == ';' || line[0] == '#') {
continue; continue;
} }
@ -128,8 +107,15 @@ void config::read() {
string key{string_util::trim(line.substr(0, equal_pos), ' ')}; string key{string_util::trim(line.substr(0, equal_pos), ' ')};
string value{string_util::trim(string_util::trim(line.substr(equal_pos + 1), ' '), '"')}; string value{string_util::trim(string_util::trim(line.substr(equal_pos + 1), ' '), '"')};
m_sections[section][key] = move(value); auto it = m_sections[section].find(key);
if (it != m_sections[section].end()) {
throw key_error("Duplicate key name \"" + key + "\" defined on line " + to_string(lineno));
}
m_sections[section].emplace_hint(it, move(key), move(value));
} }
copy_inherited();
} }
/** /**
@ -198,27 +184,39 @@ short config::convert(string&& value) const {
template <> template <>
bool config::convert(string&& value) const { bool config::convert(string&& value) const {
return std::atoi(value.c_str()) != 0; string lower{string_util::lower(forward<string>(value))};
if (lower.compare(0, 4, "true") == 0) {
return true;
} else if (lower.compare(0, 3, "yes") == 0) {
return true;
} else if (lower.compare(0, 2, "on") == 0) {
return true;
} else if (lower.compare(0, 1, "1") == 0) {
return true;
} else {
return false;
}
} }
template <> template <>
float config::convert(string&& value) const { float config::convert(string&& value) const {
return std::atof(value.c_str()); return std::strtof(value.c_str(), nullptr);
} }
template <> template <>
double config::convert(string&& value) const { double config::convert(string&& value) const {
return std::atof(value.c_str()); return std::strtod(value.c_str(), nullptr);
} }
template <> template <>
long config::convert(string&& value) const { long config::convert(string&& value) const {
return std::atol(value.c_str()); return std::strtol(value.c_str(), nullptr, 10);
} }
template <> template <>
long long config::convert(string&& value) const { long long config::convert(string&& value) const {
return std::atoll(value.c_str()); return std::strtoll(value.c_str(), nullptr, 10);
} }
template <> template <>
@ -267,4 +265,14 @@ unsigned long long config::convert(string&& value) const {
return std::strtoull(value.c_str(), nullptr, 10); return std::strtoull(value.c_str(), nullptr, 10);
} }
template <>
chrono::seconds config::convert(string&& value) const {
return chrono::seconds{convert<chrono::seconds::rep>(forward<string>(value))};
}
template <>
chrono::milliseconds config::convert(string&& value) const {
return chrono::milliseconds{convert<chrono::milliseconds::rep>(forward<string>(value))};
}
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -96,6 +96,7 @@ controller::~controller() {
void controller::setup() { void controller::setup() {
string bs{m_conf.bar_section()}; string bs{m_conf.bar_section()};
string bs{m_conf.section()};
m_log.trace("controller: Setup user-defined modules"); m_log.trace("controller: Setup user-defined modules");
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {

View File

@ -109,25 +109,24 @@ int main(int argc, char** argv) {
// Dump requested data // Dump requested data
//================================================== //==================================================
if (cli->has("dump")) { if (cli->has("dump")) {
std::cout << conf.get<string>(conf.bar_section(), cli->get("dump")) << std::endl; std::cout << conf.get<string>(conf.section(), cli->get("dump")) << std::endl;
throw exit_success{}; throw exit_success{};
} }
//================================================== //==================================================
// Create controller and run application // Create controller and run application
//================================================== //==================================================
unique_ptr<controller> ctrl;
string path_confwatch; string path_confwatch;
bool enable_ipc{false}; bool enable_ipc{false};
if (!cli->has("print-wmname")) { if (!cli->has("print-wmname")) {
enable_ipc = conf.get<bool>(conf.bar_section(), "enable-ipc", false); enable_ipc = conf.get<bool>(conf.section(), "enable-ipc", false);
} }
if (!cli->has("print-wmname") && cli->has("reload")) { if (!cli->has("print-wmname") && cli->has("reload")) {
path_confwatch = conf.filepath(); path_confwatch = conf.filepath();
} }
ctrl = controller::make(move(path_confwatch), enable_ipc, cli->has("stdout")); unique_ptr<controller> ctrl{controller::make(move(path_confwatch), move(enable_ipc), cli->has("stdout"))};
if (cli->has("print-wmname")) { if (cli->has("print-wmname")) {
std::cout << ctrl->opts().wmname << std::endl; std::cout << ctrl->opts().wmname << std::endl;

View File

@ -62,7 +62,7 @@ tray_manager::~tray_manager() {
void tray_manager::setup(const bar_settings& bar_opts) { void tray_manager::setup(const bar_settings& bar_opts) {
auto conf = config::make(); auto conf = config::make();
auto bs = conf.bar_section(); auto bs = conf.section();
auto tray_position = conf.get<string>(bs, "tray-position", ""); auto tray_position = conf.get<string>(bs, "tray-position", "");
if (tray_position == "left") { if (tray_position == "left") {