mirror of https://github.com/polybar/polybar.git
Compare commits
8 Commits
0a23199911
...
751ac7a5cc
Author | SHA1 | Date |
---|---|---|
dvermd | 751ac7a5cc | |
Roddy Rappaport | 11b522c313 | |
Roddy Rappaport | 82a81ce07c | |
Roddy Rappaport | c2dd279bf7 | |
patrick96 | 174ce34285 | |
dvermd | b5070bbc32 | |
dvermd | c9bba89d52 | |
dvermd | 9ff6d0cb10 |
|
@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- An option `unmute-on-scroll` for `internal/pulseaudio` and `internal/alsa` to unmute audio when the user scrolls on the widget.
|
||||||
|
|
||||||
## [3.7.1] - 2023-11-27
|
## [3.7.1] - 2023-11-27
|
||||||
### Build
|
### Build
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
modules = {
|
||||||
|
i3_test = {
|
||||||
|
type = "internal/i3",
|
||||||
|
-- this syntax is needed for key containing '-' or reserved word
|
||||||
|
[ "wrapping-scroll" ] = true,
|
||||||
|
format = "<label-state> <label-mode>"
|
||||||
|
},
|
||||||
|
mydate = {
|
||||||
|
type = "internal/date",
|
||||||
|
internal = "5",
|
||||||
|
date = " %Y-%m-%d",
|
||||||
|
time = "%H:%M",
|
||||||
|
["time-alt"] = "%H:%M:%S",
|
||||||
|
["format-underline"] = "#0a6cf5",
|
||||||
|
label = "%date% %time%"
|
||||||
|
},
|
||||||
|
fs1 = {
|
||||||
|
type = "internal/fs",
|
||||||
|
interval = "25",
|
||||||
|
mount = {"/"},
|
||||||
|
["label-mounted"] = "%{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%",
|
||||||
|
["label-unmounted"] = "%mountpoint% not mounted",
|
||||||
|
["label-unmounted-foreground"] = "#555555"
|
||||||
|
},
|
||||||
|
fs2 = {
|
||||||
|
type = "internal/fs",
|
||||||
|
interval = 25,
|
||||||
|
mount = {"/home"},
|
||||||
|
["label-mounted"] = "%{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%",
|
||||||
|
["label-unmounted"] = "%mountpoint% not mounted",
|
||||||
|
["label-unmounted-foreground"] = "#555555"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bars = {
|
||||||
|
bar_test = {
|
||||||
|
monitor = "eDP-1",
|
||||||
|
width = "100%",
|
||||||
|
height = "18",
|
||||||
|
radius = 4.0,
|
||||||
|
["fixed-center"] = false,
|
||||||
|
-- background = {"#222222", "#444444"},
|
||||||
|
background = "#222222",
|
||||||
|
foreground = "#dfdfdf",
|
||||||
|
font = {"fixed:pixelsize=10;1"},
|
||||||
|
["enable-ipc"] = true,
|
||||||
|
["modules-center"] = "i3_test mydate fs1 fs2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
sphinx~=7.2.6
|
sphinx~=7.2.6
|
||||||
sphinx-rtd-theme~=2.0.0rc2
|
sphinx-rtd-theme~=2.0.0rc2
|
||||||
sphinx-notfound-page~=1.0.0
|
sphinx-notfound-page~=1.0.0
|
||||||
readthedocs-sphinx-search~=0.3.1
|
readthedocs-sphinx-search~=0.3.2
|
||||||
|
|
|
@ -153,6 +153,9 @@ internal/alsa
|
||||||
``interval`` is the config setting in the module. Volume changed like this
|
``interval`` is the config setting in the module. Volume changed like this
|
||||||
will never go above 100%.
|
will never go above 100%.
|
||||||
|
|
||||||
|
if ``unmute-on-scroll`` is turned on, the sound will also be unmuted when
|
||||||
|
this action is called.
|
||||||
|
|
||||||
:``toggle``:
|
:``toggle``:
|
||||||
Toggles between muted and unmuted.
|
Toggles between muted and unmuted.
|
||||||
|
|
||||||
|
@ -165,6 +168,9 @@ internal/pulseaudio
|
||||||
will never go above ~153% (if ``use-ui-max`` is set to ``true``) or 100% (if
|
will never go above ~153% (if ``use-ui-max`` is set to ``true``) or 100% (if
|
||||||
not).
|
not).
|
||||||
|
|
||||||
|
if ``unmute-on-scroll`` is turned on, the sound will also be unmuted when
|
||||||
|
this action is called.
|
||||||
|
|
||||||
:``toggle``:
|
:``toggle``:
|
||||||
Toggles between muted and unmuted.
|
Toggles between muted and unmuted.
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "components/config.hpp"
|
||||||
#include "components/eventloop.hpp"
|
#include "components/eventloop.hpp"
|
||||||
#include "components/types.hpp"
|
#include "components/types.hpp"
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
|
|
|
@ -3,64 +3,80 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "components/config_base.hpp"
|
||||||
|
#include "components/config_ini.hpp"
|
||||||
|
#include "components/config_lua.hpp"
|
||||||
#include "components/logger.hpp"
|
#include "components/logger.hpp"
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "utils/env.hpp"
|
|
||||||
#include "utils/file.hpp"
|
|
||||||
#include "utils/string.hpp"
|
|
||||||
#if WITH_XRM
|
|
||||||
#include "x11/xresources.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
DEFINE_ERROR(value_error);
|
|
||||||
DEFINE_ERROR(key_error);
|
|
||||||
|
|
||||||
using valuemap_t = std::unordered_map<string, string>;
|
|
||||||
using sectionmap_t = std::map<string, valuemap_t>;
|
|
||||||
using file_list = vector<string>;
|
|
||||||
|
|
||||||
class config {
|
class config {
|
||||||
public:
|
public:
|
||||||
explicit config(const logger& logger, string&& path, string&& bar)
|
explicit config(const logger& logger, const string& path)
|
||||||
: m_log(logger), m_file(move(path)), m_barname(move(bar)){};
|
: m_log(logger), m_file(path){};
|
||||||
|
|
||||||
const string& filepath() const;
|
shared_ptr<config_ini> make_ini(const std::string& barname) {
|
||||||
string section() const;
|
m_barname = barname;
|
||||||
|
m_config_ini = make_shared<config_ini>(m_log, m_file, m_barname);
|
||||||
|
return m_config_ini;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr const char* BAR_PREFIX = "bar/";
|
shared_ptr<config_lua> make_lua(const std::string& barname) {
|
||||||
|
m_barname = barname;
|
||||||
|
m_config_lua = make_shared<config_lua>(m_log, m_file, m_barname);
|
||||||
|
return m_config_lua;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const string& filepath() const {
|
||||||
* @brief Instruct the config to connect to the xresource manager
|
return m_file;
|
||||||
*/
|
}
|
||||||
void use_xrm();
|
string section() const {
|
||||||
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->section();
|
||||||
|
} else {
|
||||||
|
return m_config_lua->section();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void set_sections(sectionmap_t sections);
|
file_list get_included_files() const {
|
||||||
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->get_included_files();
|
||||||
|
} else {
|
||||||
|
return m_config_lua->get_included_files();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void set_included(file_list included);
|
void warn_deprecated(const string& section, const string& key, string replacement="") const {
|
||||||
|
if (m_config_ini) {
|
||||||
file_list get_included_files() const;
|
return m_config_ini->warn_deprecated(section, key, replacement);
|
||||||
|
} else {
|
||||||
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
return m_config_lua->warn_deprecated(section, key, replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a given parameter exists
|
* Returns true if a given parameter exists
|
||||||
*/
|
*/
|
||||||
bool has(const string& section, const string& key) const;
|
bool has(const string& section, const string& key) const {
|
||||||
|
if (m_config_ini) {
|
||||||
/**
|
return m_config_ini->has(section, key);
|
||||||
* Set parameter value
|
} else {
|
||||||
*/
|
return m_config_lua->has(section, key);
|
||||||
void set(const string& section, const string& key, string&& value);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get parameter for the current bar by name
|
* Get parameter for the current bar by name
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
T get(const string& key) const {
|
T get(const string& key) const {
|
||||||
return get<T>(section(), key);
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->get<T>(key);
|
||||||
|
} else {
|
||||||
|
return m_config_lua->get<T>(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,14 +84,11 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
T get(const string& section, const string& key) const {
|
T get(const string& section, const string& key) const {
|
||||||
auto it = m_sections.find(section);
|
if (m_config_ini) {
|
||||||
if (it == m_sections.end()) {
|
return m_config_ini->get<T>(section, key);
|
||||||
throw key_error("Missing section \"" + section + "\"");
|
} else {
|
||||||
|
return m_config_lua->get<T>(section, key);
|
||||||
}
|
}
|
||||||
if (it->second.find(key) == it->second.end()) {
|
|
||||||
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
|
||||||
}
|
|
||||||
return convert<T>(dereference(section, key, it->second.at(key)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,14 +97,10 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
T get(const string& section, const string& key, const T& default_value) const {
|
T get(const string& section, const string& key, const T& default_value) const {
|
||||||
try {
|
if (m_config_ini) {
|
||||||
string string_value{get<string>(section, key)};
|
return m_config_ini->get<T>(section, key, default_value);
|
||||||
return convert<T>(dereference(move(section), move(key), move(string_value)));
|
} else {
|
||||||
} catch (const key_error& err) {
|
return m_config_lua->get<T>(section, key, default_value);
|
||||||
return default_value;
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what());
|
|
||||||
return default_value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,22 +112,11 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||||
auto it = m_sections.find(section);
|
if (m_config_ini) {
|
||||||
if (it == m_sections.end()) {
|
return m_config_ini->get_with_prefix<T>(section, key_prefix);
|
||||||
throw key_error("Missing section \"" + section + "\"");
|
} else {
|
||||||
|
return m_config_lua->get_with_prefix<T>(section, key_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<string, T>> list;
|
|
||||||
for (const auto& kv_pair : it->second) {
|
|
||||||
const auto& key = kv_pair.first;
|
|
||||||
|
|
||||||
if (key.substr(0, key_prefix.size()) == key_prefix) {
|
|
||||||
const T& val = get<T>(section, key);
|
|
||||||
list.emplace_back(key.substr(key_prefix.size()), val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,7 +124,11 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
vector<T> get_list(const string& key) const {
|
vector<T> get_list(const string& key) const {
|
||||||
return get_list<T>(section(), key);
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->get_list<T>(key);
|
||||||
|
} else {
|
||||||
|
return m_config_lua->get_list<T>(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,27 +136,11 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
vector<T> get_list(const string& section, const string& key) const {
|
vector<T> get_list(const string& section, const string& key) const {
|
||||||
vector<T> results;
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->get_list<T>(section, key);
|
||||||
while (true) {
|
} else {
|
||||||
try {
|
return m_config_lua->get_list<T>(section, key);
|
||||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
|
||||||
|
|
||||||
if (!string_value.empty()) {
|
|
||||||
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
|
||||||
} else {
|
|
||||||
results.emplace_back(convert<T>(move(string_value)));
|
|
||||||
}
|
|
||||||
} catch (const key_error& err) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.empty()) {
|
|
||||||
throw key_error("Missing parameter \"" + section + "." + key + "-0\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,31 +149,11 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||||
vector<T> results;
|
if (m_config_ini) {
|
||||||
|
return m_config_ini->get_list<T>(section, key, default_value);
|
||||||
while (true) {
|
} else {
|
||||||
try {
|
return m_config_lua->get_list<T>(section, key, default_value);
|
||||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
|
||||||
|
|
||||||
if (!string_value.empty()) {
|
|
||||||
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
|
||||||
} else {
|
|
||||||
results.emplace_back(convert<T>(move(string_value)));
|
|
||||||
}
|
|
||||||
} catch (const key_error& err) {
|
|
||||||
break;
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what());
|
|
||||||
return default_value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!results.empty()) {
|
|
||||||
return results;
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return default_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,76 +163,20 @@ class config {
|
||||||
*/
|
*/
|
||||||
template <typename T = string>
|
template <typename T = string>
|
||||||
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
|
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
|
||||||
try {
|
if (m_config_ini) {
|
||||||
T value{get<T>(section, old)};
|
return m_config_ini->deprecated<T>(section, old, newkey, fallback);
|
||||||
warn_deprecated(section, old, newkey);
|
} else {
|
||||||
return value;
|
return m_config_lua->deprecated<T>(section, old, newkey, fallback);
|
||||||
} catch (const key_error& err) {
|
|
||||||
return get<T>(section, newkey, fallback);
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
|
||||||
err.what());
|
|
||||||
return get<T>(section, newkey, fallback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
void copy_inherited();
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T convert(string&& value) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dereference value reference
|
|
||||||
*/
|
|
||||||
string dereference(const string& section, const string& key, const string& var) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dereference local value reference defined using:
|
|
||||||
* ${root.key}
|
|
||||||
* ${root.key:fallback}
|
|
||||||
* ${self.key}
|
|
||||||
* ${self.key:fallback}
|
|
||||||
* ${section.key}
|
|
||||||
* ${section.key:fallback}
|
|
||||||
*/
|
|
||||||
string dereference_local(string section, const string& key, const string& current_section) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dereference environment variable reference defined using:
|
|
||||||
* ${env:key}
|
|
||||||
* ${env:key:fallback value}
|
|
||||||
*/
|
|
||||||
string dereference_env(string var) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dereference X resource db value defined using:
|
|
||||||
* ${xrdb:key}
|
|
||||||
* ${xrdb:key:fallback value}
|
|
||||||
*/
|
|
||||||
string dereference_xrdb(string var) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dereference file reference by reading its contents
|
|
||||||
* ${file:/absolute/file/path}
|
|
||||||
* ${file:/absolute/file/path:fallback value}
|
|
||||||
*/
|
|
||||||
string dereference_file(string var) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
string m_file;
|
string m_file;
|
||||||
string m_barname;
|
string m_barname;
|
||||||
sectionmap_t m_sections{};
|
|
||||||
|
|
||||||
/**
|
shared_ptr<config_ini> m_config_ini;
|
||||||
* Absolute path of all files that were parsed in the process of parsing the
|
shared_ptr<config_lua> m_config_lua;
|
||||||
* config (Path of the main config file also included)
|
|
||||||
*/
|
|
||||||
file_list m_included;
|
|
||||||
#if WITH_XRM
|
|
||||||
unique_ptr<xresource_manager> m_xrm;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "errors.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
DEFINE_ERROR(value_error);
|
||||||
|
DEFINE_ERROR(key_error);
|
||||||
|
|
||||||
|
using valuemap_t = std::unordered_map<string, string>;
|
||||||
|
using sectionmap_t = std::map<string, valuemap_t>;
|
||||||
|
using file_list = vector<string>;
|
||||||
|
|
||||||
|
namespace config_utils {
|
||||||
|
template <typename T>
|
||||||
|
T convert(string&& value);
|
||||||
|
};
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
|
@ -0,0 +1,263 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "components/config_base.hpp"
|
||||||
|
#include "components/logger.hpp"
|
||||||
|
#include "errors.hpp"
|
||||||
|
#include "settings.hpp"
|
||||||
|
#include "utils/env.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
#if WITH_XRM
|
||||||
|
#include "x11/xresources.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
class config_ini {
|
||||||
|
public:
|
||||||
|
explicit config_ini(const logger& logger, const string& path, const string& bar)
|
||||||
|
: m_log(logger), m_file(path), m_barname(bar){};
|
||||||
|
|
||||||
|
const string& filepath() const;
|
||||||
|
string section() const;
|
||||||
|
|
||||||
|
static constexpr const char* BAR_PREFIX = "bar/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Instruct the config to connect to the xresource manager
|
||||||
|
*/
|
||||||
|
void use_xrm();
|
||||||
|
|
||||||
|
void set_sections(sectionmap_t sections);
|
||||||
|
|
||||||
|
void set_included(file_list included);
|
||||||
|
|
||||||
|
file_list get_included_files() const;
|
||||||
|
|
||||||
|
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists
|
||||||
|
*/
|
||||||
|
bool has(const string& section, const string& key) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameter value
|
||||||
|
*/
|
||||||
|
void set(const string& section, const string& key, string&& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parameter for the current bar by name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
T get(const string& key) const {
|
||||||
|
return get<T>(section(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value of a variable by section and parameter name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
T get(const string& section, const string& key) const {
|
||||||
|
auto it = m_sections.find(section);
|
||||||
|
if (it == m_sections.end()) {
|
||||||
|
throw key_error("Missing section \"" + section + "\"");
|
||||||
|
}
|
||||||
|
if (it->second.find(key) == it->second.end()) {
|
||||||
|
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
||||||
|
}
|
||||||
|
return config_utils::convert<T>(dereference(section, key, it->second.at(key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value of a variable by section and parameter name
|
||||||
|
* with a default value in case the parameter isn't defined
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
T get(const string& section, const string& key, const T& default_value) const {
|
||||||
|
try {
|
||||||
|
string string_value{get<string>(section, key)};
|
||||||
|
return config_utils::convert<T>(dereference(move(section), move(key), move(string_value)));
|
||||||
|
} catch (const key_error& err) {
|
||||||
|
return default_value;
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what());
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of key-value pairs starting with a prefix by section.
|
||||||
|
*
|
||||||
|
* Eg: if you have in config `env-FOO = bar`,
|
||||||
|
* get_with_prefix(section, "env-") will return [{"FOO", "bar"}]
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||||
|
auto it = m_sections.find(section);
|
||||||
|
if (it == m_sections.end()) {
|
||||||
|
throw key_error("Missing section \"" + section + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pair<string, T>> list;
|
||||||
|
for (const auto& kv_pair : it->second) {
|
||||||
|
const auto& key = kv_pair.first;
|
||||||
|
|
||||||
|
if (key.substr(0, key_prefix.size()) == key_prefix) {
|
||||||
|
const T& val = get<T>(section, key);
|
||||||
|
list.emplace_back(key.substr(key_prefix.size()), val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values for the current bar by name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& key) const {
|
||||||
|
return get_list<T>(section(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values by section and parameter name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& section, const string& key) const {
|
||||||
|
vector<T> results;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||||
|
|
||||||
|
if (!string_value.empty()) {
|
||||||
|
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
|
||||||
|
} else {
|
||||||
|
results.emplace_back( config_utils::convert<T>(move(string_value)));
|
||||||
|
}
|
||||||
|
} catch (const key_error& err) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.empty()) {
|
||||||
|
throw key_error("Missing parameter \"" + section + "." + key + "-0\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values by section and parameter name
|
||||||
|
* with a default list in case the list isn't defined
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||||
|
vector<T> results;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||||
|
|
||||||
|
if (!string_value.empty()) {
|
||||||
|
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
|
||||||
|
} else {
|
||||||
|
results.emplace_back( config_utils::convert<T>(move(string_value)));
|
||||||
|
}
|
||||||
|
} catch (const key_error& err) {
|
||||||
|
break;
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what());
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!results.empty()) {
|
||||||
|
return results;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = string>
|
||||||
|
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);
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||||
|
err.what());
|
||||||
|
return get<T>(section, newkey, fallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void copy_inherited();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dereference value reference
|
||||||
|
*/
|
||||||
|
string dereference(const string& section, const string& key, const string& var) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dereference local value reference defined using:
|
||||||
|
* ${root.key}
|
||||||
|
* ${root.key:fallback}
|
||||||
|
* ${self.key}
|
||||||
|
* ${self.key:fallback}
|
||||||
|
* ${section.key}
|
||||||
|
* ${section.key:fallback}
|
||||||
|
*/
|
||||||
|
string dereference_local(string section, const string& key, const string& current_section) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dereference environment variable reference defined using:
|
||||||
|
* ${env:key}
|
||||||
|
* ${env:key:fallback value}
|
||||||
|
*/
|
||||||
|
string dereference_env(string var) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dereference X resource db value defined using:
|
||||||
|
* ${xrdb:key}
|
||||||
|
* ${xrdb:key:fallback value}
|
||||||
|
*/
|
||||||
|
string dereference_xrdb(string var) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dereference file reference by reading its contents
|
||||||
|
* ${file:/absolute/file/path}
|
||||||
|
* ${file:/absolute/file/path:fallback value}
|
||||||
|
*/
|
||||||
|
string dereference_file(string var) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const logger& m_log;
|
||||||
|
string m_file;
|
||||||
|
string m_barname;
|
||||||
|
sectionmap_t m_sections{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute path of all files that were parsed in the process of parsing the
|
||||||
|
* config (Path of the main config file also included)
|
||||||
|
*/
|
||||||
|
file_list m_included;
|
||||||
|
#if WITH_XRM
|
||||||
|
unique_ptr<xresource_manager> m_xrm;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
|
@ -0,0 +1,294 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "components/config_base.hpp"
|
||||||
|
#include "components/types.hpp"
|
||||||
|
#include "components/logger.hpp"
|
||||||
|
#include "errors.hpp"
|
||||||
|
#include "settings.hpp"
|
||||||
|
#include "utils/color.hpp"
|
||||||
|
#include "utils/env.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
#include <sol/sol.hpp>
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
class config_lua {
|
||||||
|
public:
|
||||||
|
explicit config_lua(const logger& logger, const string& path, const string& bar)
|
||||||
|
: m_log(logger), m_file(path), m_barname(bar){
|
||||||
|
m_state.open_libraries();
|
||||||
|
|
||||||
|
m_state.script_file(path, [](lua_State*, sol::protected_function_result pfr) -> sol::protected_function_result {
|
||||||
|
sol::error err = pfr;
|
||||||
|
throw application_error(string("Error loading lua config: ") + err.what(), 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (m_barname.empty()) {
|
||||||
|
sol::optional<sol::table> opt_bars = m_state[BARS_CONTAINER];
|
||||||
|
if (opt_bars) {
|
||||||
|
sol::table bars = *opt_bars;
|
||||||
|
|
||||||
|
vector<string> keys(bars.size());
|
||||||
|
for (const pair<sol::object, sol::object> &kv_pair: bars) {
|
||||||
|
sol::object k = kv_pair.first;
|
||||||
|
if (k.is<string>()) {
|
||||||
|
keys.push_back(k.as<string>());
|
||||||
|
} else {
|
||||||
|
throw application_error("The config file contains a bar with a non string name.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys.size() == 1) {
|
||||||
|
m_barname = keys[0];
|
||||||
|
} else if (bars.empty()){
|
||||||
|
throw application_error("The config file contains no bar.");
|
||||||
|
} else {
|
||||||
|
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||||
|
string_util::join(keys, ", "));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw application_error("The config file contains no bar.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& filepath() const;
|
||||||
|
string section() const;
|
||||||
|
|
||||||
|
static constexpr const char* BARS_CONTAINER = "bars";
|
||||||
|
static constexpr const char* MODULES_CONTAINER = "modules";
|
||||||
|
|
||||||
|
file_list get_included_files() const;
|
||||||
|
|
||||||
|
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists
|
||||||
|
*/
|
||||||
|
bool has(const string& section, const string& key) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parameter for the current bar by name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
T get(const string& key) const {
|
||||||
|
return get<T>(section(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value of a variable by section and parameter name
|
||||||
|
*/
|
||||||
|
template <typename T=string>
|
||||||
|
T get(const string& section, const string& key) const {
|
||||||
|
return config_utils::convert<T>(move(lua_get<string>(section, key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T=string>
|
||||||
|
T get(const string& section, const string& key, const T& default_value) const {
|
||||||
|
try {
|
||||||
|
return get<T>(section, key);
|
||||||
|
} catch (const key_error& err) {
|
||||||
|
return default_value;
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
pair<string, std::optional<string>> entries = get_entries(section);
|
||||||
|
if (entries.second){
|
||||||
|
m_log.err("Invalid value for \"%s[%s][%s]\", using default value (reason: %s)", entries.first, *entries.second, key, err.what());
|
||||||
|
} else {
|
||||||
|
m_log.err("Invalid value for \"%s[%s]\", using default value (reason: %s)", entries.first, key, err.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of key-value pairs starting with a prefix by section.
|
||||||
|
*
|
||||||
|
* Eg: if you have in config `env-FOO = bar`,
|
||||||
|
* get_with_prefix(section, "env-") will return [{"FOO", "bar"}]
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||||
|
pair<sol::table, string> table_message = lua_get_table(section);
|
||||||
|
sol::table table = table_message.first;
|
||||||
|
vector<pair<string, T>> kv_vec;
|
||||||
|
for (const pair<sol::object, sol::object> &kv_pair: table) {
|
||||||
|
sol::object k = kv_pair.first;
|
||||||
|
sol::object v = kv_pair.second;
|
||||||
|
if (k.is<string>()) {
|
||||||
|
string k_str = k.as<string>();
|
||||||
|
if (k_str.substr(0, key_prefix.size()) == key_prefix) {
|
||||||
|
if (v.is<T>()) {
|
||||||
|
kv_vec.push_back({k_str, v.as<T>()});
|
||||||
|
} else if (v.is<string>()) {
|
||||||
|
kv_vec.push_back({k_str, config_utils::convert<T>(move(v.as<string>()))});
|
||||||
|
} else {
|
||||||
|
throw value_error("Wrong data type for \"" + table_message.second+ "[" + k_str + "]\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return kv_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values for the current bar by name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& key) const {
|
||||||
|
return get_list<T>(section(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values by section and parameter name
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& section, const string& key) const {
|
||||||
|
pair<sol::table, string> table_message = lua_get_table(section);
|
||||||
|
sol::table table = table_message.first;
|
||||||
|
string message_key = table_message.second;
|
||||||
|
|
||||||
|
if (!config_lua::has(table, key)) {
|
||||||
|
throw key_error("Missing parameter \"" + message_key + "[" + key + "]\"");
|
||||||
|
}
|
||||||
|
sol::optional<vector<sol::optional<string>>> value = table[key];
|
||||||
|
if (value == sol::nullopt) {
|
||||||
|
sol::optional<string> value = table[key];
|
||||||
|
if (value != sol::nullopt) {
|
||||||
|
throw key_error("Not a list value for parameter \"" + message_key + "[" + key + "]\"");
|
||||||
|
} else {
|
||||||
|
throw value_error("Wrong type for parameter \"" + message_key + "[" + key + "]\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<sol::optional<string>> vec = *value;
|
||||||
|
vector<T> result{vec.size()};
|
||||||
|
for (size_t i = 0; i < vec.size(); i++) {
|
||||||
|
const sol::optional<string>& value = vec[i];
|
||||||
|
if (value) {
|
||||||
|
string value_str = *value;
|
||||||
|
result.push_back(config_utils::convert<T>(move(value_str)));
|
||||||
|
} else {
|
||||||
|
throw value_error("The element of \"" + message_key + "\" at position " + to_string(i) + " cannot be converted to the expected type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of values by section and parameter name
|
||||||
|
* with a default list in case the list isn't defined
|
||||||
|
*/
|
||||||
|
template <typename T = string>
|
||||||
|
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||||
|
try {
|
||||||
|
vector<T> results = get_list<T>(section, key);
|
||||||
|
if (!results.empty()) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
return default_value;
|
||||||
|
|
||||||
|
} catch (const key_error&) {
|
||||||
|
return default_value;
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
pair<string, std::optional<string>> entries = get_entries(section);
|
||||||
|
if (entries.second){
|
||||||
|
m_log.err("Invalid value for \"%s[%s][%s]\", using list as-is (reason: %s)", entries.first, *entries.second, key, err.what());
|
||||||
|
} else {
|
||||||
|
m_log.err("Invalid value for \"%s[%s]\", using list as-is (reason: %s)", entries.first, key, err.what());
|
||||||
|
}
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = string>
|
||||||
|
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);
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
// TODO improve message
|
||||||
|
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||||
|
err.what());
|
||||||
|
pair<string, std::optional<string>> entries = get_entries(section);
|
||||||
|
if (entries.second){
|
||||||
|
m_log.err("Invalid value for \"%s[%s][%s]\", fallback key \"%s[%s][%s]\" (reason: %s)", entries.first, *entries.second, old, entries.first, *entries.second, newkey, err.what());
|
||||||
|
} else {
|
||||||
|
m_log.err("Invalid value for \"%s[%s]\", fallback key \"%s[%s]\" (reason: %s)", entries.first, old, entries.first, newkey, err.what());
|
||||||
|
}
|
||||||
|
return get<T>(section, newkey, fallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pair<string, std::optional<string>> get_entries(const string& section) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists in the lua table
|
||||||
|
*/
|
||||||
|
static bool has(const sol::table& table, const string& key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists in the lua table
|
||||||
|
*/
|
||||||
|
static bool has(const sol::state& table, const string& key);
|
||||||
|
|
||||||
|
pair<sol::table, string> lua_get_table(const string& section) const;
|
||||||
|
|
||||||
|
template <typename T=string>
|
||||||
|
T lua_get(const string& section, const string& key) const {
|
||||||
|
pair<string, std::optional<string>> entries = get_entries(section);
|
||||||
|
|
||||||
|
if (!config_lua::has(m_state, entries.first)) {
|
||||||
|
throw key_error("Missing entry \"" + entries.first + "\"");
|
||||||
|
}
|
||||||
|
sol::optional<sol::table> opt_table = m_state[entries.first];
|
||||||
|
if (opt_table == sol::nullopt) {
|
||||||
|
throw key_error("Wrong type for entry \"" + entries.first + "\": expecting table");
|
||||||
|
}
|
||||||
|
string message_key = entries.first;
|
||||||
|
sol::table table = *opt_table;
|
||||||
|
if (entries.second) {
|
||||||
|
message_key += "[" + *entries.second + "]";
|
||||||
|
if (!config_lua::has(table, *entries.second)) {
|
||||||
|
throw key_error("Missing entry \"" + message_key + "\"");
|
||||||
|
}
|
||||||
|
sol::optional<sol::table> opt_table = table[*entries.second];
|
||||||
|
if (opt_table == sol::nullopt) {
|
||||||
|
throw key_error("Wrong type for entry \"" + message_key + "\": expecting table");
|
||||||
|
}
|
||||||
|
table = *opt_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_lua::has(table, key)) {
|
||||||
|
throw key_error("Missing parameter \"" + message_key + "[" + key + "]\"");
|
||||||
|
}
|
||||||
|
sol::optional<T> value = table[key];
|
||||||
|
if (value) {
|
||||||
|
return *value;
|
||||||
|
} else {
|
||||||
|
throw value_error("Wrong type for parameter \"" + message_key + "[" + key + "]\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const logger& m_log;
|
||||||
|
string m_file;
|
||||||
|
string m_barname;
|
||||||
|
sol::state m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
|
@ -215,6 +215,8 @@ class config_parser {
|
||||||
*/
|
*/
|
||||||
bool is_valid_name(const string& name);
|
bool is_valid_name(const string& name);
|
||||||
|
|
||||||
|
bool is_lua_file() const;
|
||||||
|
|
||||||
vector<string> get_bars(const sectionmap_t& sections) const;
|
vector<string> get_bars(const sectionmap_t& sections) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace modules {
|
||||||
map<control, control_t> m_ctrl;
|
map<control, control_t> m_ctrl;
|
||||||
int m_headphoneid{0};
|
int m_headphoneid{0};
|
||||||
bool m_mapped{false};
|
bool m_mapped{false};
|
||||||
|
bool m_unmute_on_scroll{false};
|
||||||
int m_interval{5};
|
int m_interval{5};
|
||||||
atomic<bool> m_muted{false};
|
atomic<bool> m_muted{false};
|
||||||
atomic<bool> m_headphones{false};
|
atomic<bool> m_headphones{false};
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace modules {
|
||||||
pulseaudio_t m_pulseaudio;
|
pulseaudio_t m_pulseaudio;
|
||||||
|
|
||||||
int m_interval{5};
|
int m_interval{5};
|
||||||
|
bool m_unmute_on_scroll{false};
|
||||||
atomic<bool> m_muted{false};
|
atomic<bool> m_muted{false};
|
||||||
atomic<int> m_volume{0};
|
atomic<int> m_volume{0};
|
||||||
atomic<double> m_decibels{0};
|
atomic<double> m_decibels{0};
|
||||||
|
|
|
@ -36,3 +36,13 @@ if(ENABLE_I3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
# Library: sol2 {{{
|
||||||
|
|
||||||
|
# if(ENABLE_LUA)
|
||||||
|
add_library(sol2 INTERFACE)
|
||||||
|
target_include_directories(sol2 INTERFACE ${PROJECT_SOURCE_DIR}/lib/sol2)
|
||||||
|
target_link_libraries(sol2 INTERFACE lua)
|
||||||
|
target_compile_definitions(sol2 INTERFACE SOL_ALL_SAFETIES_ON=1)
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013-2022 Rapptz, ThePhD, and contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,53 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
// This file was generated with a script.
|
||||||
|
// Generated 2022-06-25 08:14:19.336233 UTC
|
||||||
|
// This header was generated with sol v3.3.0 (revision eba86625)
|
||||||
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
|
#ifndef SOL_SINGLE_CONFIG_HPP
|
||||||
|
#define SOL_SINGLE_CONFIG_HPP
|
||||||
|
|
||||||
|
// beginning of sol/config.hpp
|
||||||
|
|
||||||
|
/* Base, empty configuration file!
|
||||||
|
|
||||||
|
To override, place a file in your include paths of the form:
|
||||||
|
|
||||||
|
. (your include path here)
|
||||||
|
| sol (directory, or equivalent)
|
||||||
|
| config.hpp (your config.hpp file)
|
||||||
|
|
||||||
|
So that when sol2 includes the file
|
||||||
|
|
||||||
|
#include <sol/config.hpp>
|
||||||
|
|
||||||
|
it gives you the configuration values you desire. Configuration values can be
|
||||||
|
seen in the safety.rst of the doc/src, or at
|
||||||
|
https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through
|
||||||
|
the build system, or the command line options of your compiler.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// end of sol/config.hpp
|
||||||
|
|
||||||
|
#endif // SOL_SINGLE_CONFIG_HPP
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -60,7 +60,9 @@ set(POLY_SOURCES
|
||||||
${src_dir}/components/bar.cpp
|
${src_dir}/components/bar.cpp
|
||||||
${src_dir}/components/builder.cpp
|
${src_dir}/components/builder.cpp
|
||||||
${src_dir}/components/command_line.cpp
|
${src_dir}/components/command_line.cpp
|
||||||
${src_dir}/components/config.cpp
|
${src_dir}/components/config_base.cpp
|
||||||
|
${src_dir}/components/config_ini.cpp
|
||||||
|
${src_dir}/components/config_lua.cpp
|
||||||
${src_dir}/components/config_parser.cpp
|
${src_dir}/components/config_parser.cpp
|
||||||
${src_dir}/components/controller.cpp
|
${src_dir}/components/controller.cpp
|
||||||
${src_dir}/components/logger.cpp
|
${src_dir}/components/logger.cpp
|
||||||
|
@ -161,6 +163,7 @@ target_link_libraries(poly PUBLIC
|
||||||
Cairo::CairoFC
|
Cairo::CairoFC
|
||||||
xpp
|
xpp
|
||||||
LibUV::LibUV
|
LibUV::LibUV
|
||||||
|
sol2
|
||||||
)
|
)
|
||||||
|
|
||||||
if (TARGET i3ipc++)
|
if (TARGET i3ipc++)
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
#include "components/config_base.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "cairo/utils.hpp"
|
||||||
|
#include "components/types.hpp"
|
||||||
|
#include "utils/color.hpp"
|
||||||
|
#include "utils/factory.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
#include "utils/units.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace chrono = std::chrono;
|
||||||
|
namespace config_utils {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
string convert(string&& value) {
|
||||||
|
return forward<string>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const char* convert(string&& value) {
|
||||||
|
return value.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
char convert(string&& value) {
|
||||||
|
return value.c_str()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int convert(string&& value) {
|
||||||
|
return std::strtol(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
short convert(string&& value) {
|
||||||
|
return static_cast<short>(std::strtol(value.c_str(), nullptr, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool convert(string&& value) {
|
||||||
|
string lower{string_util::lower(forward<string>(value))};
|
||||||
|
|
||||||
|
return (lower == "true" || lower == "yes" || lower == "on" || lower == "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
float convert(string&& value) {
|
||||||
|
return std::strtof(value.c_str(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
double convert(string&& value) {
|
||||||
|
return std::strtod(value.c_str(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
long convert(string&& value) {
|
||||||
|
return std::strtol(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
long long convert(string&& value) {
|
||||||
|
return std::strtoll(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
unsigned char convert(string&& value) {
|
||||||
|
return std::strtoul(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
unsigned short convert(string&& value) {
|
||||||
|
return std::strtoul(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
unsigned int convert(string&& value) {
|
||||||
|
return std::strtoul(value.c_str(), nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
unsigned long convert(string&& value) {
|
||||||
|
unsigned long v{std::strtoul(value.c_str(), nullptr, 10)};
|
||||||
|
return v < ULONG_MAX ? v : 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
unsigned long long convert(string&& value) {
|
||||||
|
unsigned long long v{std::strtoull(value.c_str(), nullptr, 10)};
|
||||||
|
return v < ULLONG_MAX ? v : 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
spacing_val convert(string&& value) {
|
||||||
|
return units_utils::parse_spacing(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
extent_val convert(std::string&& value) {
|
||||||
|
return units_utils::parse_extent(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows a new format for pixel sizes (like width in the bar section)
|
||||||
|
*
|
||||||
|
* The new format is X%:Z, where X is in [0, 100], and Z is any real value
|
||||||
|
* describing a pixel offset. The actual value is calculated by X% * max + Z
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
percentage_with_offset convert(string&& value) {
|
||||||
|
size_t i = value.find(':');
|
||||||
|
|
||||||
|
if (i == std::string::npos) {
|
||||||
|
if (value.find('%') != std::string::npos) {
|
||||||
|
return {std::stod(value), {}};
|
||||||
|
} else {
|
||||||
|
return {0., convert<extent_val>(move(value))};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string percentage = value.substr(0, i - 1);
|
||||||
|
return {std::stod(percentage), convert<extent_val>(value.substr(i + 1))};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
chrono::seconds convert(string&& value) {
|
||||||
|
return chrono::seconds{convert<chrono::seconds::rep>(forward<string>(value))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
chrono::milliseconds convert(string&& value) {
|
||||||
|
return chrono::milliseconds{convert<chrono::milliseconds::rep>(forward<string>(value))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
chrono::duration<double> convert(string&& value) {
|
||||||
|
return chrono::duration<double>{convert<double>(forward<string>(value))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
rgba convert(string&& value) {
|
||||||
|
if (value.empty()) {
|
||||||
|
return rgba{};
|
||||||
|
}
|
||||||
|
|
||||||
|
rgba ret{value};
|
||||||
|
|
||||||
|
if (!ret.has_color()) {
|
||||||
|
throw value_error("\"" + value + "\" is an invalid color value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
cairo_operator_t convert(string&& value) {
|
||||||
|
return cairo::utils::str2operator(forward<string>(value), CAIRO_OPERATOR_OVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
|
@ -1,16 +1,4 @@
|
||||||
#include "components/config.hpp"
|
#include "components/config_ini.hpp"
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <cmath>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "cairo/utils.hpp"
|
|
||||||
#include "components/types.hpp"
|
|
||||||
#include "utils/color.hpp"
|
|
||||||
#include "utils/env.hpp"
|
|
||||||
#include "utils/factory.hpp"
|
|
||||||
#include "utils/string.hpp"
|
|
||||||
#include "utils/units.hpp"
|
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
|
@ -19,18 +7,18 @@ namespace chrono = std::chrono;
|
||||||
/**
|
/**
|
||||||
* Get path of loaded file
|
* Get path of loaded file
|
||||||
*/
|
*/
|
||||||
const string& config::filepath() const {
|
const string& config_ini::filepath() const {
|
||||||
return m_file;
|
return m_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the section name of the bar in use
|
* Get the section name of the bar in use
|
||||||
*/
|
*/
|
||||||
string config::section() const {
|
string config_ini::section() const {
|
||||||
return BAR_PREFIX + m_barname;
|
return BAR_PREFIX + m_barname;
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::use_xrm() {
|
void config_ini::use_xrm() {
|
||||||
#if WITH_XRM
|
#if WITH_XRM
|
||||||
/*
|
/*
|
||||||
* Initialize the xresource manager if there are any xrdb refs
|
* Initialize the xresource manager if there are any xrdb refs
|
||||||
|
@ -43,23 +31,23 @@ void config::use_xrm() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::set_sections(sectionmap_t sections) {
|
void config_ini::set_sections(sectionmap_t sections) {
|
||||||
m_sections = move(sections);
|
m_sections = move(sections);
|
||||||
copy_inherited();
|
copy_inherited();
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::set_included(file_list included) {
|
void config_ini::set_included(file_list included) {
|
||||||
m_included = move(included);
|
m_included = move(included);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_list config::get_included_files() const {
|
file_list config_ini::get_included_files() const {
|
||||||
return m_included;
|
return m_included;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a deprecation warning if the given parameter is set
|
* Print a deprecation warning if the given parameter is set
|
||||||
*/
|
*/
|
||||||
void config::warn_deprecated(const string& section, const string& key, string replacement) const {
|
void config_ini::warn_deprecated(const string& section, const string& key, string replacement) const {
|
||||||
if (has(section, key)) {
|
if (has(section, key)) {
|
||||||
if (replacement.empty()) {
|
if (replacement.empty()) {
|
||||||
m_log.warn(
|
m_log.warn(
|
||||||
|
@ -76,7 +64,7 @@ void config::warn_deprecated(const string& section, const string& key, string re
|
||||||
/**
|
/**
|
||||||
* Returns true if a given parameter exists
|
* Returns true if a given parameter exists
|
||||||
*/
|
*/
|
||||||
bool config::has(const string& section, const string& key) const {
|
bool config_ini::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();
|
||||||
}
|
}
|
||||||
|
@ -84,7 +72,7 @@ bool config::has(const string& section, const string& key) const {
|
||||||
/**
|
/**
|
||||||
* Set parameter value
|
* Set parameter value
|
||||||
*/
|
*/
|
||||||
void config::set(const string& section, const string& key, string&& value) {
|
void config_ini::set(const string& section, const string& key, string&& value) {
|
||||||
auto it = m_sections.find(section);
|
auto it = m_sections.find(section);
|
||||||
if (it == m_sections.end()) {
|
if (it == m_sections.end()) {
|
||||||
valuemap_t values;
|
valuemap_t values;
|
||||||
|
@ -108,7 +96,7 @@ void config::set(const string& section, const string& key, string&& value) {
|
||||||
* [sub/section]
|
* [sub/section]
|
||||||
* inherit = section1 section2
|
* inherit = section1 section2
|
||||||
*/
|
*/
|
||||||
void config::copy_inherited() {
|
void config_ini::copy_inherited() {
|
||||||
for (auto&& section : m_sections) {
|
for (auto&& section : m_sections) {
|
||||||
std::vector<string> inherit_sections;
|
std::vector<string> inherit_sections;
|
||||||
|
|
||||||
|
@ -163,7 +151,7 @@ void config::copy_inherited() {
|
||||||
/**
|
/**
|
||||||
* Dereference value reference
|
* Dereference value reference
|
||||||
*/
|
*/
|
||||||
string config::dereference(const string& section, const string& key, const string& var) const {
|
string config_ini::dereference(const string& section, const string& key, const string& var) const {
|
||||||
if (var.substr(0, 2) != "${" || var.substr(var.length() - 1) != "}") {
|
if (var.substr(0, 2) != "${" || var.substr(var.length() - 1) != "}") {
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +181,7 @@ string config::dereference(const string& section, const string& key, const strin
|
||||||
* ${section.key}
|
* ${section.key}
|
||||||
* ${section.key:fallback}
|
* ${section.key:fallback}
|
||||||
*/
|
*/
|
||||||
string config::dereference_local(string section, const string& key, const string& current_section) const {
|
string config_ini::dereference_local(string section, const string& key, const string& current_section) const {
|
||||||
if (section == "BAR") {
|
if (section == "BAR") {
|
||||||
m_log.warn("${BAR.key} is deprecated. Use ${root.key} instead");
|
m_log.warn("${BAR.key} is deprecated. Use ${root.key} instead");
|
||||||
}
|
}
|
||||||
|
@ -222,7 +210,7 @@ string config::dereference_local(string section, const string& key, const string
|
||||||
* ${env:key}
|
* ${env:key}
|
||||||
* ${env:key:fallback value}
|
* ${env:key:fallback value}
|
||||||
*/
|
*/
|
||||||
string config::dereference_env(string var) const {
|
string config_ini::dereference_env(string var) const {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
string env_default;
|
string env_default;
|
||||||
/*
|
/*
|
||||||
|
@ -254,7 +242,7 @@ string config::dereference_env(string var) const {
|
||||||
* ${xrdb:key}
|
* ${xrdb:key}
|
||||||
* ${xrdb:key:fallback value}
|
* ${xrdb:key:fallback value}
|
||||||
*/
|
*/
|
||||||
string config::dereference_xrdb(string var) const {
|
string config_ini::dereference_xrdb(string var) const {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
#if not WITH_XRM
|
#if not WITH_XRM
|
||||||
m_log.warn("No built-in support to dereference ${xrdb:%s} references (requires `xcb-util-xrm`)", var);
|
m_log.warn("No built-in support to dereference ${xrdb:%s} references (requires `xcb-util-xrm`)", var);
|
||||||
|
@ -294,7 +282,7 @@ string config::dereference_xrdb(string var) const {
|
||||||
* ${file:/absolute/file/path}
|
* ${file:/absolute/file/path}
|
||||||
* ${file:/absolute/file/path:fallback value}
|
* ${file:/absolute/file/path:fallback value}
|
||||||
*/
|
*/
|
||||||
string config::dereference_file(string var) const {
|
string config_ini::dereference_file(string var) const {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
string fallback;
|
string fallback;
|
||||||
bool has_fallback = false;
|
bool has_fallback = false;
|
||||||
|
@ -316,151 +304,4 @@ string config::dereference_file(string var) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
string config::convert(string&& value) const {
|
|
||||||
return forward<string>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
const char* config::convert(string&& value) const {
|
|
||||||
return value.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
char config::convert(string&& value) const {
|
|
||||||
return value.c_str()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
int config::convert(string&& value) const {
|
|
||||||
return std::strtol(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
short config::convert(string&& value) const {
|
|
||||||
return static_cast<short>(std::strtol(value.c_str(), nullptr, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
bool config::convert(string&& value) const {
|
|
||||||
string lower{string_util::lower(forward<string>(value))};
|
|
||||||
|
|
||||||
return (lower == "true" || lower == "yes" || lower == "on" || lower == "1");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
float config::convert(string&& value) const {
|
|
||||||
return std::strtof(value.c_str(), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
double config::convert(string&& value) const {
|
|
||||||
return std::strtod(value.c_str(), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
long config::convert(string&& value) const {
|
|
||||||
return std::strtol(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
long long config::convert(string&& value) const {
|
|
||||||
return std::strtoll(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
unsigned char config::convert(string&& value) const {
|
|
||||||
return std::strtoul(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
unsigned short config::convert(string&& value) const {
|
|
||||||
return std::strtoul(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
unsigned int config::convert(string&& value) const {
|
|
||||||
return std::strtoul(value.c_str(), nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
unsigned long config::convert(string&& value) const {
|
|
||||||
unsigned long v{std::strtoul(value.c_str(), nullptr, 10)};
|
|
||||||
return v < ULONG_MAX ? v : 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
unsigned long long config::convert(string&& value) const {
|
|
||||||
unsigned long long v{std::strtoull(value.c_str(), nullptr, 10)};
|
|
||||||
return v < ULLONG_MAX ? v : 0ULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
spacing_val config::convert(string&& value) const {
|
|
||||||
return units_utils::parse_spacing(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
extent_val config::convert(std::string&& value) const {
|
|
||||||
return units_utils::parse_extent(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows a new format for pixel sizes (like width in the bar section)
|
|
||||||
*
|
|
||||||
* The new format is X%:Z, where X is in [0, 100], and Z is any real value
|
|
||||||
* describing a pixel offset. The actual value is calculated by X% * max + Z
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
percentage_with_offset config::convert(string&& value) const {
|
|
||||||
size_t i = value.find(':');
|
|
||||||
|
|
||||||
if (i == std::string::npos) {
|
|
||||||
if (value.find('%') != std::string::npos) {
|
|
||||||
return {std::stod(value), {}};
|
|
||||||
} else {
|
|
||||||
return {0., convert<extent_val>(move(value))};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::string percentage = value.substr(0, i - 1);
|
|
||||||
return {std::stod(percentage), convert<extent_val>(value.substr(i + 1))};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
chrono::duration<double> config::convert(string&& value) const {
|
|
||||||
return chrono::duration<double>{convert<double>(forward<string>(value))};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
rgba config::convert(string&& value) const {
|
|
||||||
if (value.empty()) {
|
|
||||||
return rgba{};
|
|
||||||
}
|
|
||||||
|
|
||||||
rgba ret{value};
|
|
||||||
|
|
||||||
if (!ret.has_color()) {
|
|
||||||
throw value_error("\"" + value + "\" is an invalid color value.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
cairo_operator_t config::convert(string&& value) const {
|
|
||||||
return cairo::utils::str2operator(forward<string>(value), CAIRO_OPERATOR_OVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include "components/config_lua.hpp"
|
||||||
|
#include "utils/units.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace chrono = std::chrono;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path of loaded file
|
||||||
|
*/
|
||||||
|
const string& config_lua::filepath() const {
|
||||||
|
return m_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the section name of the bar in use
|
||||||
|
*/
|
||||||
|
string config_lua::section() const {
|
||||||
|
return m_barname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a deprecation warning if the given parameter is set
|
||||||
|
*/
|
||||||
|
void config_lua::warn_deprecated(const string& section, const string& key, string replacement) const {
|
||||||
|
if (has(section, key)) {
|
||||||
|
if (replacement.empty()) {
|
||||||
|
m_log.warn(
|
||||||
|
"The config parameter '%s.%s' is deprecated, it will be removed in the future. Please remove it from your "
|
||||||
|
"config",
|
||||||
|
section, key);
|
||||||
|
} else {
|
||||||
|
m_log.warn(
|
||||||
|
"The config parameter `%s.%s` is deprecated, use `%s.%s` instead.", section, key, section, move(replacement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool config_lua::has(const string& section, const string& key) const {
|
||||||
|
try {
|
||||||
|
pair<sol::table, string> table_message = lua_get_table(section);
|
||||||
|
return config_lua::has(table_message.first, key);
|
||||||
|
} catch (const key_error&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_list config_lua::get_included_files() const {
|
||||||
|
file_list fl{m_file};
|
||||||
|
return fl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool config_lua::get(const string& section, const string& key) const {
|
||||||
|
return lua_get<bool>(section, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
double config_lua::get(const string& section, const string& key) const {
|
||||||
|
return lua_get<double>(section, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
size_t config_lua::get(const string& section, const string& key) const {
|
||||||
|
return lua_get<size_t>(section, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int config_lua::get(const string& section, const string& key) const {
|
||||||
|
return lua_get<int>(section, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<string, std::optional<string>> config_lua::get_entries(const string& section) const {
|
||||||
|
if (section == m_barname) {
|
||||||
|
return {BARS_CONTAINER, section};
|
||||||
|
} else if (section == "settings") {
|
||||||
|
return {section, std::nullopt};
|
||||||
|
} else {
|
||||||
|
// split section which should look like "module/xyz" into "modules" and "xyz"
|
||||||
|
return {MODULES_CONTAINER, section.substr(strlen("module/"))};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists in the lua table
|
||||||
|
*/
|
||||||
|
bool config_lua::has(const sol::table& table, const string& key) {
|
||||||
|
for (const pair<sol::object, sol::object> &p: table) {
|
||||||
|
sol::object k = p.first;
|
||||||
|
if (k.is<string>() && k.as<string>() == key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given parameter exists in the lua table
|
||||||
|
*/
|
||||||
|
bool config_lua::has(const sol::state& table, const string& key) {
|
||||||
|
for (const pair<sol::object, sol::object> &p: table) {
|
||||||
|
sol::object k = p.first;
|
||||||
|
if (k.is<string>() && k.as<string>() == key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<sol::table, string> config_lua::lua_get_table(const string& section) const {
|
||||||
|
pair<string, std::optional<string>> entries = get_entries(section);
|
||||||
|
|
||||||
|
if (!config_lua::has(m_state, entries.first)) {
|
||||||
|
throw key_error("Missing entry \"" + entries.first + "\"");
|
||||||
|
}
|
||||||
|
sol::optional<sol::table> opt_table = m_state[entries.first];
|
||||||
|
if (opt_table == sol::nullopt) {
|
||||||
|
throw key_error("Wrong type for entry \"" + entries.first + "\": expecting table");
|
||||||
|
}
|
||||||
|
string message_key = entries.first;
|
||||||
|
sol::table table = *opt_table;
|
||||||
|
if (entries.second) {
|
||||||
|
message_key += "[" + *entries.second + "]";
|
||||||
|
if (!config_lua::has(table, *entries.second)) {
|
||||||
|
throw key_error("Missing entry \"" + message_key + "\"");
|
||||||
|
}
|
||||||
|
sol::optional<sol::table> opt_table = table[*entries.second];
|
||||||
|
if (opt_table == sol::nullopt) {
|
||||||
|
throw key_error("Wrong type for entry \"" + message_key + "\": expecting table");
|
||||||
|
}
|
||||||
|
table = *opt_table;
|
||||||
|
}
|
||||||
|
return {table, message_key};
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
|
@ -5,6 +5,8 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "components/config_ini.hpp"
|
||||||
|
#include "components/config_lua.hpp"
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
@ -15,45 +17,50 @@ config_parser::config_parser(const logger& logger, string&& file)
|
||||||
|
|
||||||
config config_parser::parse(string barname) {
|
config config_parser::parse(string barname) {
|
||||||
m_log.notice("Parsing config file: %s", m_config_file);
|
m_log.notice("Parsing config file: %s", m_config_file);
|
||||||
|
config config(m_log, m_config_file);
|
||||||
|
|
||||||
parse_file(m_config_file, {});
|
if (is_lua_file()) {
|
||||||
|
shared_ptr<config_lua> conf_lua = config.make_lua(barname);
|
||||||
|
return config;
|
||||||
|
} else {
|
||||||
|
parse_file(m_config_file, {});
|
||||||
|
|
||||||
sectionmap_t sections = create_sectionmap();
|
sectionmap_t sections = create_sectionmap();
|
||||||
|
|
||||||
vector<string> bars = get_bars(sections);
|
vector<string> bars = get_bars(sections);
|
||||||
if (barname.empty()) {
|
if (barname.empty()) {
|
||||||
if (bars.size() == 1) {
|
if (bars.size() == 1) {
|
||||||
barname = bars[0];
|
barname = bars[0];
|
||||||
} else if (bars.empty()) {
|
} else if (bars.empty()) {
|
||||||
throw application_error("The config file contains no bar.");
|
throw application_error("The config file contains no bar.");
|
||||||
} else {
|
} else {
|
||||||
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||||
string_util::join(bars, ", "));
|
string_util::join(bars, ", "));
|
||||||
|
}
|
||||||
|
} else if (sections.find("bar/" + barname) == sections.end()) {
|
||||||
|
if (bars.empty()) {
|
||||||
|
throw application_error("Undefined bar: " + barname + ". The config file contains no bar.");
|
||||||
|
} else {
|
||||||
|
throw application_error(
|
||||||
|
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (sections.find("bar/" + barname) == sections.end()) {
|
|
||||||
if (bars.empty()) {
|
/*
|
||||||
throw application_error("Undefined bar: " + barname + ". The config file contains no bar.");
|
* The first element in the files vector is always the main config file and
|
||||||
} else {
|
* because it has unique filenames, we can use all the elements from the
|
||||||
throw application_error(
|
* second element onwards for the included list
|
||||||
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
*/
|
||||||
|
file_list included(m_files.begin() + 1, m_files.end());
|
||||||
|
shared_ptr<config_ini> conf_ini = config.make_ini(barname);
|
||||||
|
|
||||||
|
conf_ini->set_sections(move(sections));
|
||||||
|
conf_ini->set_included(move(included));
|
||||||
|
if (use_xrm) {
|
||||||
|
conf_ini->use_xrm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return config;
|
||||||
/*
|
|
||||||
* The first element in the files vector is always the main config file and
|
|
||||||
* because it has unique filenames, we can use all the elements from the
|
|
||||||
* second element onwards for the included list
|
|
||||||
*/
|
|
||||||
file_list included(m_files.begin() + 1, m_files.end());
|
|
||||||
config conf(m_log, move(m_config_file), move(barname));
|
|
||||||
|
|
||||||
conf.set_sections(move(sections));
|
|
||||||
conf.set_included(move(included));
|
|
||||||
if (use_xrm) {
|
|
||||||
conf.use_xrm();
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionmap_t config_parser::create_sectionmap() {
|
sectionmap_t config_parser::create_sectionmap() {
|
||||||
|
@ -98,8 +105,8 @@ sectionmap_t config_parser::create_sectionmap() {
|
||||||
vector<string> config_parser::get_bars(const sectionmap_t& sections) const {
|
vector<string> config_parser::get_bars(const sectionmap_t& sections) const {
|
||||||
vector<string> bars;
|
vector<string> bars;
|
||||||
for (const auto& it : sections) {
|
for (const auto& it : sections) {
|
||||||
if (it.first.find(config::BAR_PREFIX) == 0) {
|
if (it.first.find(config_ini::BAR_PREFIX) == 0) {
|
||||||
bars.push_back(it.first.substr(strlen(config::BAR_PREFIX)));
|
bars.push_back(it.first.substr(strlen(config_ini::BAR_PREFIX)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bars;
|
return bars;
|
||||||
|
@ -309,6 +316,10 @@ bool config_parser::is_valid_name(const string& name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool config_parser::is_lua_file() const {
|
||||||
|
return m_config_file.substr(m_config_file.size() - 4) == ".lua";
|
||||||
|
}
|
||||||
|
|
||||||
string config_parser::parse_escaped_value(const line_t& line, string&& value, const string& key) {
|
string config_parser::parse_escaped_value(const line_t& line, string&& value, const string& key) {
|
||||||
string cfg_value = value;
|
string cfg_value = value;
|
||||||
bool log = false;
|
bool log = false;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace modules {
|
||||||
// Load configuration values
|
// Load configuration values
|
||||||
m_mapped = m_conf.get(name(), "mapped", m_mapped);
|
m_mapped = m_conf.get(name(), "mapped", m_mapped);
|
||||||
m_interval = m_conf.get(name(), "interval", m_interval);
|
m_interval = m_conf.get(name(), "interval", m_interval);
|
||||||
|
m_unmute_on_scroll = m_conf.get(name(), "unmute-on-scroll", m_unmute_on_scroll);
|
||||||
|
|
||||||
auto master_mixer_name = m_conf.get(name(), "master-mixer", "Master"s);
|
auto master_mixer_name = m_conf.get(name(), "master-mixer", "Master"s);
|
||||||
auto speaker_mixer_name = m_conf.get(name(), "speaker-mixer", ""s);
|
auto speaker_mixer_name = m_conf.get(name(), "speaker-mixer", ""s);
|
||||||
|
@ -261,6 +262,9 @@ namespace modules {
|
||||||
}
|
}
|
||||||
const auto& mixers = get_mixers();
|
const auto& mixers = get_mixers();
|
||||||
for (auto&& mixer : mixers) {
|
for (auto&& mixer : mixers) {
|
||||||
|
if (m_unmute_on_scroll) {
|
||||||
|
mixer->set_mute(true);
|
||||||
|
}
|
||||||
m_mapped ? mixer->set_normalized_volume(math_util::cap<float>(mixer->get_normalized_volume() + interval, 0, 100))
|
m_mapped ? mixer->set_normalized_volume(math_util::cap<float>(mixer->get_normalized_volume() + interval, 0, 100))
|
||||||
: mixer->set_volume(math_util::cap<float>(mixer->get_volume() + interval, 0, 100));
|
: mixer->set_volume(math_util::cap<float>(mixer->get_volume() + interval, 0, 100));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace modules {
|
||||||
|
|
||||||
// Load configuration values
|
// Load configuration values
|
||||||
m_interval = m_conf.get(name(), "interval", m_interval);
|
m_interval = m_conf.get(name(), "interval", m_interval);
|
||||||
|
m_unmute_on_scroll = m_conf.get(name(), "unmute-on-scroll", m_unmute_on_scroll);
|
||||||
|
|
||||||
auto sink_name = m_conf.get(name(), "sink", ""s);
|
auto sink_name = m_conf.get(name(), "sink", ""s);
|
||||||
bool m_max_volume = m_conf.get(name(), "use-ui-max", true);
|
bool m_max_volume = m_conf.get(name(), "use-ui-max", true);
|
||||||
|
@ -156,10 +157,16 @@ namespace modules {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulseaudio_module::action_inc() {
|
void pulseaudio_module::action_inc() {
|
||||||
|
if (m_unmute_on_scroll) {
|
||||||
|
m_pulseaudio->set_mute(false);
|
||||||
|
}
|
||||||
m_pulseaudio->inc_volume(m_interval);
|
m_pulseaudio->inc_volume(m_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulseaudio_module::action_dec() {
|
void pulseaudio_module::action_dec() {
|
||||||
|
if (m_unmute_on_scroll) {
|
||||||
|
m_pulseaudio->set_mute(false);
|
||||||
|
}
|
||||||
m_pulseaudio->inc_volume(-m_interval);
|
m_pulseaudio->inc_volume(-m_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue