working minimal lua config implementation using sol2 wrapper

This commit is contained in:
dvermd 2023-04-27 15:40:26 +02:00
parent c9bba89d52
commit b5070bbc32
15 changed files with 31091 additions and 239 deletions

50
doc/config.lua Normal file
View File

@ -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"
}
}

View File

@ -5,48 +5,66 @@
#include "common.hpp"
#include "components/config_base.hpp"
#include "components/config_ini.hpp"
// #include "components/config_lua.hpp"
#include "components/config_lua.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 {
public:
explicit config(const logger& logger, const string& path, const string& bar)
: m_log(logger), m_file(path), m_barname(bar){};
shared_ptr<config_ini> make_ini() {
explicit config(const logger& logger, const string& path)
: m_log(logger), m_file(path){};
shared_ptr<config_ini> make_ini(const std::string& barname) {
m_barname = barname;
m_config_ini = make_shared<config_ini>(m_log, m_file, m_barname);
return m_config_ini;
}
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 {
return m_config_ini->filepath();
return m_file;
}
string section() const {
return m_config_ini->section();
if (m_config_ini) {
return m_config_ini->section();
} else {
return m_config_lua->section();
}
}
file_list get_included_files() const {
return m_config_ini->get_included_files();
if (m_config_ini) {
return m_config_ini->get_included_files();
} else {
return m_config_lua->get_included_files();
}
}
void warn_deprecated(const string& section, const string& key, string replacement="") const {
return m_config_ini->warn_deprecated(section, key, replacement);
if (m_config_ini) {
return m_config_ini->warn_deprecated(section, key, replacement);
} else {
return m_config_lua->warn_deprecated(section, key, replacement);
}
}
/**
* Returns true if a given parameter exists
*/
bool has(const string& section, const string& key) const {
return m_config_ini->has(section, key);
if (m_config_ini) {
return m_config_ini->has(section, key);
} else {
return m_config_lua->has(section, key);
}
}
/**
@ -54,7 +72,11 @@ class config {
*/
template <typename T = string>
T get(const string& key) const {
return m_config_ini->get<T>(key);
if (m_config_ini) {
return m_config_ini->get<T>(key);
} else {
return m_config_lua->get<T>(key);
}
}
/**
@ -62,7 +84,11 @@ class config {
*/
template <typename T = string>
T get(const string& section, const string& key) const {
return m_config_ini->get<T>(section, key);
if (m_config_ini) {
return m_config_ini->get<T>(section, key);
} else {
return m_config_lua->get<T>(section, key);
}
}
/**
@ -71,7 +97,11 @@ class config {
*/
template <typename T = string>
T get(const string& section, const string& key, const T& default_value) const {
return m_config_ini->get<T>(section, key, default_value);
if (m_config_ini) {
return m_config_ini->get<T>(section, key, default_value);
} else {
return m_config_lua->get<T>(section, key, default_value);
}
}
/**
@ -82,7 +112,11 @@ class config {
*/
template <typename T = string>
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
return m_config_ini->get_with_prefix<T>(section, key_prefix);
if (m_config_ini) {
return m_config_ini->get_with_prefix<T>(section, key_prefix);
} else {
return m_config_lua->get_with_prefix<T>(section, key_prefix);
}
}
/**
@ -90,7 +124,11 @@ class config {
*/
template <typename T = string>
vector<T> get_list(const string& key) const {
return m_config_ini->get_list<T>(key);
if (m_config_ini) {
return m_config_ini->get_list<T>(key);
} else {
return m_config_lua->get_list<T>(key);
}
}
/**
@ -98,7 +136,11 @@ class config {
*/
template <typename T = string>
vector<T> get_list(const string& section, const string& key) const {
return m_config_ini->get_list<T>(section, key);
if (m_config_ini) {
return m_config_ini->get_list<T>(section, key);
} else {
return m_config_lua->get_list<T>(section, key);
}
}
/**
@ -107,7 +149,11 @@ class config {
*/
template <typename T = string>
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
return m_config_ini->get_list<T>(section, key, default_value);
if (m_config_ini) {
return m_config_ini->get_list<T>(section, key, default_value);
} else {
return m_config_lua->get_list<T>(section, key, default_value);
}
}
/**
@ -117,7 +163,11 @@ class config {
*/
template <typename T = string>
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
return m_config_ini->deprecated<T>(section, old, newkey, fallback);
if (m_config_ini) {
return m_config_ini->deprecated<T>(section, old, newkey, fallback);
} else {
return m_config_lua->deprecated<T>(section, old, newkey, fallback);
}
}
private:
@ -126,6 +176,7 @@ class config {
string m_barname;
shared_ptr<config_ini> m_config_ini;
shared_ptr<config_lua> m_config_lua;
};
POLYBAR_NS_END

View File

@ -4,9 +4,8 @@
#include <unordered_map>
#include <vector>
// #include "common.hpp"
#include "common.hpp"
#include "errors.hpp"
// #include "settings.hpp"
POLYBAR_NS
@ -17,4 +16,9 @@ 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

View File

@ -69,7 +69,7 @@ class config_ini {
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)));
return config_utils::convert<T>(dereference(section, key, it->second.at(key)));
}
/**
@ -80,7 +80,7 @@ class config_ini {
T get(const string& section, const string& key, const T& default_value) const {
try {
string string_value{get<string>(section, key)};
return convert<T>(dereference(move(section), move(key), move(string_value)));
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) {
@ -135,9 +135,9 @@ class config_ini {
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))));
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
} else {
results.emplace_back(convert<T>(move(string_value)));
results.emplace_back( config_utils::convert<T>(move(string_value)));
}
} catch (const key_error& err) {
break;
@ -164,9 +164,9 @@ class config_ini {
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))));
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
} else {
results.emplace_back(convert<T>(move(string_value)));
results.emplace_back( config_utils::convert<T>(move(string_value)));
}
} catch (const key_error& err) {
break;
@ -207,9 +207,6 @@ class config_ini {
protected:
void copy_inherited();
template <typename T>
T convert(string&& value) const;
/**
* Dereference value reference
*/

View File

@ -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

View File

@ -36,3 +36,13 @@ if(ENABLE_I3)
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()
# }}}

20
lib/sol2/LICENSE.txt Normal file
View File

@ -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.

53
lib/sol2/sol/config.hpp Normal file
View File

@ -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

1321
lib/sol2/sol/forward.hpp Normal file

File diff suppressed because it is too large Load Diff

28907
lib/sol2/sol/sol.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,9 @@ set(POLY_SOURCES
${src_dir}/components/bar.cpp
${src_dir}/components/builder.cpp
${src_dir}/components/command_line.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/controller.cpp
${src_dir}/components/logger.cpp
@ -161,6 +163,7 @@ target_link_libraries(poly PUBLIC
Cairo::CairoFC
xpp
LibUV::LibUV
sol2
)
if (TARGET i3ipc++)

View File

@ -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

View File

@ -1,17 +1,5 @@
#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
namespace chrono = std::chrono;
@ -76,7 +64,7 @@ void config_ini::warn_deprecated(const string& section, const string& key, strin
/**
* 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);
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
*/
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);
if (it == m_sections.end()) {
valuemap_t values;
@ -163,7 +151,7 @@ void config_ini::copy_inherited() {
/**
* 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) != "}") {
return var;
}
@ -193,7 +181,7 @@ string config::dereference(const string& section, const string& key, const strin
* ${section.key}
* ${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") {
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:fallback value}
*/
string config::dereference_env(string var) const {
string config_ini::dereference_env(string var) const {
size_t pos;
string env_default;
/*
@ -254,7 +242,7 @@ string config::dereference_env(string var) const {
* ${xrdb:key}
* ${xrdb:key:fallback value}
*/
string config::dereference_xrdb(string var) const {
string config_ini::dereference_xrdb(string var) const {
size_t pos;
#if not WITH_XRM
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:fallback value}
*/
string config::dereference_file(string var) const {
string config_ini::dereference_file(string var) const {
size_t pos;
string fallback;
bool has_fallback = false;
@ -316,151 +304,4 @@ string config::dereference_file(string var) const {
}
}
template <>
string config_ini::convert(string&& value) const {
return forward<string>(value);
}
template <>
const char* config_ini::convert(string&& value) const {
return value.c_str();
}
template <>
char config_ini::convert(string&& value) const {
return value.c_str()[0];
}
template <>
int config_ini::convert(string&& value) const {
return std::strtol(value.c_str(), nullptr, 10);
}
template <>
short config_ini::convert(string&& value) const {
return static_cast<short>(std::strtol(value.c_str(), nullptr, 10));
}
template <>
bool config_ini::convert(string&& value) const {
string lower{string_util::lower(forward<string>(value))};
return (lower == "true" || lower == "yes" || lower == "on" || lower == "1");
}
template <>
float config_ini::convert(string&& value) const {
return std::strtof(value.c_str(), nullptr);
}
template <>
double config_ini::convert(string&& value) const {
return std::strtod(value.c_str(), nullptr);
}
template <>
long config_ini::convert(string&& value) const {
return std::strtol(value.c_str(), nullptr, 10);
}
template <>
long long config_ini::convert(string&& value) const {
return std::strtoll(value.c_str(), nullptr, 10);
}
template <>
unsigned char config_ini::convert(string&& value) const {
return std::strtoul(value.c_str(), nullptr, 10);
}
template <>
unsigned short config_ini::convert(string&& value) const {
return std::strtoul(value.c_str(), nullptr, 10);
}
template <>
unsigned int config_ini::convert(string&& value) const {
return std::strtoul(value.c_str(), nullptr, 10);
}
template <>
unsigned long config_ini::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_ini::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_ini::convert(string&& value) const {
return units_utils::parse_spacing(value);
}
template <>
extent_val config_ini::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_ini::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_ini::convert(string&& value) const {
return chrono::seconds{convert<chrono::seconds::rep>(forward<string>(value))};
}
template <>
chrono::milliseconds config_ini::convert(string&& value) const {
return chrono::milliseconds{convert<chrono::milliseconds::rep>(forward<string>(value))};
}
template <>
chrono::duration<double> config_ini::convert(string&& value) const {
return chrono::duration<double>{convert<double>(forward<string>(value))};
}
template <>
rgba config_ini::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_ini::convert(string&& value) const {
return cairo::utils::str2operator(forward<string>(value), CAIRO_OPERATOR_OVER);
}
POLYBAR_NS_END

View File

@ -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

View File

@ -6,7 +6,7 @@
#include <fstream>
#include "components/config_ini.hpp"
// #include "components/config_lua.hpp"
#include "components/config_lua.hpp"
#include "utils/file.hpp"
#include "utils/string.hpp"
@ -17,49 +17,49 @@ config_parser::config_parser(const logger& logger, string&& file)
config config_parser::parse(string barname) {
m_log.notice("Parsing config file: %s", m_config_file);
config config(m_log, m_config_file, barname);
config config(m_log, m_config_file);
// if (is_lua_file()) {
// config_lua conf_lua(m_log, move(m_config_file), move(barname));
// return config::from_lua(move(conf_lua));
// } else {
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);
if (barname.empty()) {
if (bars.size() == 1) {
barname = bars[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(bars, ", "));
vector<string> bars = get_bars(sections);
if (barname.empty()) {
if (bars.size() == 1) {
barname = bars[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(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.");
} else {
throw application_error(
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
/*
* 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());
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();
}
}
/*
* 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());
shared_ptr<config_ini> conf_ini = config.make_ini();
conf_ini->set_sections(move(sections));
conf_ini->set_included(move(included));
if (use_xrm) {
conf_ini->use_xrm();
}
return config;
}
@ -317,7 +317,7 @@ bool config_parser::is_valid_name(const string& name) {
}
bool config_parser::is_lua_file() const {
return m_config_file.substr(m_config_file.size() - 4 - 1) == ".lua";
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) {