feat: Warn state for cpu, memory, fs, battery modules (#2199)

* [Temperature, Ramp] fix wrong icon for temperatures near base and warn temps

* [Temperature, Ramp] fix wrong icon for temperatures near base and warn temps

* Fix minor error

* Added WARN state for cpu module

* Implement WARN state for CPU, Memory modules, working on fs module

* Implement WARN state for fs module

* Simplify WARN state implementation for cpu and memory

* explicitly check percentage in get_by_percentage_with_borders

* Fixed silly error

* implement warn state on battery module, standardize the implementation on other modules

* minor fixes

* fix annoying error

* use more intuitive param name

* Fix percentage with borders bug

* Make requested changes
Hide the effect of warn states when unused

* Backward Compat: use no format instead of fallback label

* Reformat

* Refactor

* Reformat

* Reformat: convert tabs to spaces

* Reformat
This commit is contained in:
Quan 2020-12-02 21:55:13 +07:00 committed by GitHub
parent 078aa3c8cb
commit 39c73a8234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 245 additions and 88 deletions

View File

@ -16,7 +16,8 @@ namespace drawtypes {
void add(label_t&& icon);
label_t get(size_t index);
label_t get_by_percentage(float percentage);
label_t get_by_percentage_with_borders(float percentage);
label_t get_by_percentage_with_borders(float percentage, float min, float max);
label_t get_by_percentage_with_borders(int percentage, int min, int max);
operator bool();
protected:

View File

@ -12,6 +12,7 @@ namespace modules {
NONE = 0,
CHARGING,
DISCHARGING,
LOW,
FULL,
};
@ -68,14 +69,17 @@ namespace modules {
static constexpr const char* FORMAT_CHARGING{"format-charging"};
static constexpr const char* FORMAT_DISCHARGING{"format-discharging"};
static constexpr const char* FORMAT_FULL{"format-full"};
static constexpr const char* FORMAT_LOW{"format-low"};
static constexpr const char* TAG_ANIMATION_CHARGING{"<animation-charging>"};
static constexpr const char* TAG_ANIMATION_DISCHARGING{"<animation-discharging>"};
static constexpr const char* TAG_ANIMATION_LOW{"<animation-low>"};
static constexpr const char* TAG_BAR_CAPACITY{"<bar-capacity>"};
static constexpr const char* TAG_RAMP_CAPACITY{"<ramp-capacity>"};
static constexpr const char* TAG_LABEL_CHARGING{"<label-charging>"};
static constexpr const char* TAG_LABEL_DISCHARGING{"<label-discharging>"};
static constexpr const char* TAG_LABEL_FULL{"<label-full>"};
static constexpr const char* TAG_LABEL_LOW{"<label-low>"};
static const size_t SKIP_N_UNCHANGED{3_z};
@ -87,8 +91,10 @@ namespace modules {
label_t m_label_charging;
label_t m_label_discharging;
label_t m_label_full;
label_t m_label_low;
animation_t m_animation_charging;
animation_t m_animation_discharging;
animation_t m_animation_low;
progressbar_t m_bar_capacity;
ramp_t m_ramp_capacity;
@ -102,6 +108,7 @@ namespace modules {
int m_percentage{0};
int m_fullat{100};
int m_lowat{10};
string m_timeformat;
size_t m_unchanged{SKIP_N_UNCHANGED};
chrono::duration<double> m_interval{};

View File

@ -6,6 +6,7 @@
POLYBAR_NS
namespace modules {
enum class cpu_state { NORMAL = 0, WARN };
struct cpu_time {
unsigned long long user;
unsigned long long nice;
@ -22,6 +23,7 @@ namespace modules {
explicit cpu_module(const bar_settings&, string);
bool update();
string get_format() const;
bool build(builder* builder, const string& tag) const;
static constexpr auto TYPE = "internal/cpu";
@ -32,19 +34,24 @@ namespace modules {
private:
static constexpr auto TAG_LABEL = "<label>";
static constexpr auto TAG_LABEL_WARN = "<label-warn>";
static constexpr auto TAG_BAR_LOAD = "<bar-load>";
static constexpr auto TAG_RAMP_LOAD = "<ramp-load>";
static constexpr auto TAG_RAMP_LOAD_PER_CORE = "<ramp-coreload>";
static constexpr auto FORMAT_WARN = "format-warn";
label_t m_label;
label_t m_labelwarn;
progressbar_t m_barload;
ramp_t m_rampload;
ramp_t m_rampload_core;
label_t m_label;
int m_ramp_padding;
vector<cpu_time_t> m_cputimes;
vector<cpu_time_t> m_cputimes_prev;
float m_totalwarn = 80;
float m_total = 0;
vector<float> m_load;
};

View File

@ -46,15 +46,18 @@ namespace modules {
private:
static constexpr auto FORMAT_MOUNTED = "format-mounted";
static constexpr auto FORMAT_WARN = "format-warn";
static constexpr auto FORMAT_UNMOUNTED = "format-unmounted";
static constexpr auto TAG_LABEL_MOUNTED = "<label-mounted>";
static constexpr auto TAG_LABEL_UNMOUNTED = "<label-unmounted>";
static constexpr auto TAG_LABEL_WARN = "<label-warn>";
static constexpr auto TAG_BAR_USED = "<bar-used>";
static constexpr auto TAG_BAR_FREE = "<bar-free>";
static constexpr auto TAG_RAMP_CAPACITY = "<ramp-capacity>";
label_t m_labelmounted;
label_t m_labelunmounted;
label_t m_labelwarn;
progressbar_t m_barused;
progressbar_t m_barfree;
ramp_t m_rampcapacity;
@ -64,6 +67,7 @@ namespace modules {
bool m_fixed{false};
bool m_remove_unmounted{false};
int m_spacing{2};
int m_perc_used_warn{90};
// used while formatting output
size_t m_index{0_z};

View File

@ -7,18 +7,20 @@ POLYBAR_NS
namespace modules {
enum class memtype { NONE = 0, TOTAL, USED, FREE, SHARED, BUFFERS, CACHE, AVAILABLE };
enum class memory_state { NORMAL = 0, WARN };
class memory_module : public timer_module<memory_module> {
public:
explicit memory_module(const bar_settings&, string);
bool update();
string get_format() const;
bool build(builder* builder, const string& tag) const;
static constexpr auto TYPE = "internal/memory";
private:
static constexpr const char* TAG_LABEL{"<label>"};
static constexpr const char* TAG_LABEL_WARN{"<label-warn>"};
static constexpr const char* TAG_BAR_USED{"<bar-used>"};
static constexpr const char* TAG_BAR_FREE{"<bar-free>"};
static constexpr const char* TAG_RAMP_USED{"<ramp-used>"};
@ -27,12 +29,15 @@ namespace modules {
static constexpr const char* TAG_BAR_SWAP_FREE{"<bar-swap-free>"};
static constexpr const char* TAG_RAMP_SWAP_USED{"<ramp-swap-used>"};
static constexpr const char* TAG_RAMP_SWAP_FREE{"<ramp-swap-free>"};
static constexpr const char* FORMAT_WARN{"format-warn"};
label_t m_label;
label_t m_labelwarn;
progressbar_t m_bar_memused;
progressbar_t m_bar_memfree;
int m_perc_memused{0};
int m_perc_memfree{0};
int m_perc_memused_warn{90};
ramp_t m_ramp_memused;
ramp_t m_ramp_memfree;
progressbar_t m_bar_swapused;

View File

@ -81,11 +81,15 @@ namespace modules {
explicit module_formatter(const config& conf, string modname) : m_conf(conf), m_modname(modname) {}
void add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist = {});
void add_optional(string name, vector<string>&& tags, vector<string>&& whitelist = {});
bool has(const string& tag, const string& format_name);
bool has(const string& tag);
bool has_format(const string& format_name);
shared_ptr<module_format> get(const string& format_name);
protected:
void add_value(string&& name, string&& value, vector<string>&& tags, vector<string>&& whitelist);
const config& m_conf;
string m_modname;
map<string, shared_ptr<module_format>> m_formats;

View File

@ -35,8 +35,6 @@ namespace modules {
int m_tempbase = 0;
int m_tempwarn = 0;
int m_temp = 0;
// Percentage used in the ramp
int m_perc = 0;
// Whether or not to show units with the %temperature-X% tokens
bool m_units{true};

View File

@ -18,13 +18,18 @@ namespace drawtypes {
return m_icons[math_util::cap<size_t>(index, 0, m_icons.size() - 1)];
}
label_t ramp::get_by_percentage_with_borders(float percentage) {
label_t ramp::get_by_percentage_with_borders(int value, int min, int max) {
return get_by_percentage_with_borders(static_cast<float>(value), static_cast<float>(min), static_cast<float>(max));
}
label_t ramp::get_by_percentage_with_borders(float value, float min, float max) {
size_t index;
if (percentage <= 0.0f) {
if (value <= min) {
index = 0;
} else if (percentage >= 100.0f) {
} else if (value >= max) {
index = m_icons.size() - 1;
} else {
float percentage = math_util::percentage(value, min, max);
index = percentage * (m_icons.size() - 2) / 100.0f + 1;
index = math_util::cap<size_t>(index, 0, m_icons.size() - 1);
}

View File

@ -27,6 +27,7 @@ namespace modules {
: inotify_module<battery_module>(bar, move(name_)) {
// Load configuration values
m_fullat = math_util::min(m_conf.get(name(), "full-at", m_fullat), 100);
m_lowat = math_util::max(m_conf.get(name(), "low-at", m_lowat), 0);
m_interval = m_conf.get<decltype(m_interval)>(name(), "poll-interval", 5s);
m_lastpoll = chrono::system_clock::now();
@ -116,6 +117,7 @@ namespace modules {
{TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_CHARGING, TAG_LABEL_CHARGING});
m_formatter->add(FORMAT_DISCHARGING, TAG_LABEL_DISCHARGING,
{TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_DISCHARGING, TAG_LABEL_DISCHARGING});
m_formatter->add_optional(FORMAT_LOW, {TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_LOW, TAG_LABEL_LOW});
m_formatter->add(FORMAT_FULL, TAG_LABEL_FULL, {TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_LABEL_FULL});
if (m_formatter->has(TAG_ANIMATION_CHARGING, FORMAT_CHARGING)) {
@ -124,6 +126,9 @@ namespace modules {
if (m_formatter->has(TAG_ANIMATION_DISCHARGING, FORMAT_DISCHARGING)) {
m_animation_discharging = load_animation(m_conf, name(), TAG_ANIMATION_DISCHARGING);
}
if (m_formatter->has(TAG_ANIMATION_LOW, FORMAT_LOW)) {
m_animation_low = load_animation(m_conf, name(), TAG_ANIMATION_LOW);
}
if (m_formatter->has(TAG_BAR_CAPACITY)) {
m_bar_capacity = load_progressbar(m_bar, m_conf, name(), TAG_BAR_CAPACITY);
}
@ -136,6 +141,9 @@ namespace modules {
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING)) {
m_label_discharging = load_optional_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%%");
}
if (m_formatter->has(TAG_LABEL_LOW, FORMAT_LOW)) {
m_label_low = load_optional_label(m_conf, name(), TAG_LABEL_LOW, "%percentage%%");
}
if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL)) {
m_label_full = load_optional_label(m_conf, name(), TAG_LABEL_FULL, "%percentage%%");
}
@ -146,7 +154,8 @@ namespace modules {
// Setup time if token is used
if ((m_label_charging && m_label_charging->has_token("%time%")) ||
(m_label_discharging && m_label_discharging->has_token("%time%"))) {
(m_label_discharging && m_label_discharging->has_token("%time%")) ||
(m_label_low && m_label_low->has_token("%time%"))) {
if (!m_bar.locale.empty()) {
setlocale(LC_TIME, m_bar.locale.c_str());
}
@ -161,7 +170,7 @@ namespace modules {
void battery_module::start() {
this->inotify_module::start();
// We only start animation thread if there is at least one animation.
if (m_animation_charging || m_animation_discharging) {
if (m_animation_charging || m_animation_discharging || m_animation_low) {
m_subthread = thread(&battery_module::subthread, this);
}
}
@ -221,12 +230,11 @@ namespace modules {
m_percentage = percentage;
const auto label = [this] {
if (m_state == battery_module::state::FULL) {
return m_label_full;
} else if (m_state == battery_module::state::DISCHARGING) {
return m_label_discharging;
} else {
return m_label_charging;
switch (m_state) {
case battery_module::state::FULL: return m_label_full;
case battery_module::state::DISCHARGING: return m_label_discharging;
case battery_module::state::LOW: return m_label_low;
default: return m_label_charging;
}
}();
@ -248,12 +256,15 @@ namespace modules {
* Get the output format based on state
*/
string battery_module::get_format() const {
if (m_state == battery_module::state::CHARGING) {
return FORMAT_CHARGING;
} else if (m_state == battery_module::state::DISCHARGING) {
switch (m_state) {
case battery_module::state::FULL: return FORMAT_FULL;
case battery_module::state::LOW:
if (m_formatter->has_format(FORMAT_LOW)) {
return FORMAT_LOW;
}
return FORMAT_DISCHARGING;
} else {
return FORMAT_FULL;
case battery_module::state::DISCHARGING: return FORMAT_DISCHARGING;
default: return FORMAT_CHARGING;
}
}
@ -265,14 +276,18 @@ namespace modules {
builder->node(m_animation_charging->get());
} else if (tag == TAG_ANIMATION_DISCHARGING) {
builder->node(m_animation_discharging->get());
} else if (tag == TAG_ANIMATION_LOW) {
builder->node(m_animation_low->get());
} else if (tag == TAG_BAR_CAPACITY) {
builder->node(m_bar_capacity->output(clamp_percentage(m_percentage, m_state)));
} else if (tag == TAG_RAMP_CAPACITY) {
builder->node(m_ramp_capacity->get_by_percentage(clamp_percentage(m_percentage, m_state)));
builder->node(m_ramp_capacity->get_by_percentage_with_borders(m_percentage, m_lowat, m_fullat));
} else if (tag == TAG_LABEL_CHARGING) {
builder->node(m_label_charging);
} else if (tag == TAG_LABEL_DISCHARGING) {
builder->node(m_label_discharging);
} else if (tag == TAG_LABEL_LOW) {
builder->node(m_label_low);
} else if (tag == TAG_LABEL_FULL) {
builder->node(m_label_full);
} else {
@ -286,10 +301,11 @@ namespace modules {
* Get the current battery state
*/
battery_module::state battery_module::current_state() {
if (read(*m_capacity_reader) >= m_fullat) {
auto charge = read(*m_capacity_reader);
if (charge >= m_fullat) {
return battery_module::state::FULL;
} else if (!read(*m_state_reader)) {
return battery_module::state::DISCHARGING;
return charge <= m_lowat ? battery_module::state::LOW : battery_module::state::DISCHARGING;
} else {
return battery_module::state::CHARGING;
}
@ -358,6 +374,10 @@ namespace modules {
m_animation_discharging->increment();
broadcast();
framerate = m_animation_discharging->framerate();
} else if (m_state == battery_module::state::LOW && m_animation_low) {
m_animation_low->increment();
broadcast();
framerate = m_animation_low->framerate();
}
// We don't count the the first part of the loop to be as close as possible to the framerate.

View File

@ -17,15 +17,22 @@ namespace modules {
cpu_module::cpu_module(const bar_settings& bar, string name_) : timer_module<cpu_module>(bar, move(name_)) {
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
m_totalwarn = m_conf.get(name(), "warn-percentage", m_totalwarn);
m_ramp_padding = m_conf.get<decltype(m_ramp_padding)>(name(), "ramp-coreload-spacing", 1);
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR_LOAD, TAG_RAMP_LOAD, TAG_RAMP_LOAD_PER_CORE});
m_formatter->add_optional(FORMAT_WARN, {TAG_LABEL_WARN, TAG_BAR_LOAD, TAG_RAMP_LOAD, TAG_RAMP_LOAD_PER_CORE});
// warmup cpu times
read_values();
read_values();
if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%percentage%%");
}
if (m_formatter->has(TAG_LABEL_WARN)) {
m_labelwarn = load_optional_label(m_conf, name(), TAG_LABEL_WARN, "%percentage%%");
}
if (m_formatter->has(TAG_BAR_LOAD)) {
m_barload = load_progressbar(m_bar, m_conf, name(), TAG_BAR_LOAD);
}
@ -35,9 +42,6 @@ namespace modules {
if (m_formatter->has(TAG_RAMP_LOAD_PER_CORE)) {
m_rampload_core = load_ramp(m_conf, name(), TAG_RAMP_LOAD_PER_CORE);
}
if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%percentage%%");
}
}
bool cpu_module::update() {
@ -59,41 +63,59 @@ namespace modules {
m_total += load;
m_load.emplace_back(load);
if (m_label) {
if (m_label || m_labelwarn) {
percentage_cores.emplace_back(to_string(static_cast<int>(load + 0.5)));
}
}
m_total = m_total / static_cast<float>(cores_n);
if (m_label) {
m_label->reset_tokens();
m_label->replace_token("%percentage%", to_string(static_cast<int>(m_total + 0.5)));
m_label->replace_token("%percentage-sum%", to_string(static_cast<int>(m_total * static_cast<float>(cores_n) + 0.5)));
m_label->replace_token("%percentage-cores%", string_util::join(percentage_cores, "% ") + "%");
const auto replace_tokens = [&](label_t& label) {
label->reset_tokens();
label->replace_token("%percentage%", to_string(static_cast<int>(m_total + 0.5)));
label->replace_token("%percentage-sum%", to_string(static_cast<int>(m_total * static_cast<float>(cores_n) + 0.5)));
label->replace_token("%percentage-cores%", string_util::join(percentage_cores, "% ") + "%");
for (size_t i = 0; i < percentage_cores.size(); i++) {
m_label->replace_token("%percentage-core" + to_string(i + 1) + "%", percentage_cores[i]);
label->replace_token("%percentage-core" + to_string(i + 1) + "%", percentage_cores[i]);
}
};
if (m_label) {
replace_tokens(m_label);
}
if (m_labelwarn) {
replace_tokens(m_labelwarn);
}
return true;
}
string cpu_module::get_format() const {
if (m_total >= m_totalwarn && m_formatter->has_format(FORMAT_WARN)) {
return FORMAT_WARN;
} else {
return DEFAULT_FORMAT;
}
}
bool cpu_module::build(builder* builder, const string& tag) const {
if (tag == TAG_LABEL) {
builder->node(m_label);
} else if (tag == TAG_LABEL_WARN) {
builder->node(m_labelwarn);
} else if (tag == TAG_BAR_LOAD) {
builder->node(m_barload->output(m_total));
} else if (tag == TAG_RAMP_LOAD) {
builder->node(m_rampload->get_by_percentage(m_total));
builder->node(m_rampload->get_by_percentage_with_borders(m_total, 0.0f, m_totalwarn));
} else if (tag == TAG_RAMP_LOAD_PER_CORE) {
auto i = 0;
for (auto&& load : m_load) {
if (i++ > 0) {
builder->space(m_ramp_padding);
}
builder->node(m_rampload_core->get_by_percentage(load));
builder->node(m_rampload_core->get_by_percentage_with_borders(load, 0.0f, m_totalwarn));
}
builder->node(builder->flush());
} else {

View File

@ -28,6 +28,7 @@ namespace modules {
fs_module::fs_module(const bar_settings& bar, string name_) : timer_module<fs_module>(bar, move(name_)) {
m_mountpoints = m_conf.get_list(name(), "mount");
m_remove_unmounted = m_conf.get(name(), "remove-unmounted", m_remove_unmounted);
m_perc_used_warn = m_conf.get(name(), "warn-percentage", 90);
m_fixed = m_conf.get(name(), "fixed-values", m_fixed);
m_spacing = m_conf.get(name(), "spacing", m_spacing);
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 30s);
@ -35,11 +36,15 @@ namespace modules {
// Add formats and elements
m_formatter->add(
FORMAT_MOUNTED, TAG_LABEL_MOUNTED, {TAG_LABEL_MOUNTED, TAG_BAR_FREE, TAG_BAR_USED, TAG_RAMP_CAPACITY});
m_formatter->add_optional(FORMAT_WARN, {TAG_LABEL_WARN, TAG_BAR_FREE, TAG_BAR_USED, TAG_RAMP_CAPACITY});
m_formatter->add(FORMAT_UNMOUNTED, TAG_LABEL_UNMOUNTED, {TAG_LABEL_UNMOUNTED});
if (m_formatter->has(TAG_LABEL_MOUNTED)) {
m_labelmounted = load_optional_label(m_conf, name(), TAG_LABEL_MOUNTED, "%mountpoint% %percentage_free%%");
}
if (m_formatter->has(TAG_LABEL_WARN)) {
m_labelwarn = load_optional_label(m_conf, name(), TAG_LABEL_WARN, "%mountpoint% %percentage_free%%");
}
if (m_formatter->has(TAG_LABEL_UNMOUNTED)) {
m_labelunmounted = load_optional_label(m_conf, name(), TAG_LABEL_UNMOUNTED, "%mountpoint% is not mounted");
}
@ -104,6 +109,31 @@ namespace modules {
mount->percentage_free = math_util::percentage<double>(mount->bytes_avail, mount->bytes_used + mount->bytes_avail);
mount->percentage_used = math_util::percentage<double>(mount->bytes_used, mount->bytes_used + mount->bytes_avail);
const auto replace_tokens = [&](label_t& label) {
label->reset_tokens();
label->replace_token("%mountpoint%", mount->mountpoint);
label->replace_token("%type%", mount->type);
label->replace_token("%fsname%", mount->fsname);
label->replace_token("%percentage_free%", to_string(mount->percentage_free));
label->replace_token("%percentage_used%", to_string(mount->percentage_used));
label->replace_token(
"%total%", string_util::filesize(mount->bytes_total, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
label->replace_token(
"%free%", string_util::filesize(mount->bytes_avail, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
label->replace_token(
"%used%", string_util::filesize(mount->bytes_used, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
};
if (m_labelmounted) {
replace_tokens(m_labelmounted);
}
if (m_labelwarn) {
replace_tokens(m_labelwarn);
}
if (m_labelunmounted) {
m_labelunmounted->reset_tokens();
m_labelunmounted->replace_token("%mountpoint%", mount->mountpoint);
}
}
}
@ -141,7 +171,13 @@ namespace modules {
* Select format based on fs state
*/
string fs_module::get_format() const {
return m_mounts[m_index]->mounted ? FORMAT_MOUNTED : FORMAT_UNMOUNTED;
if (!m_mounts[m_index]->mounted) {
return FORMAT_UNMOUNTED;
}
if (m_mounts[m_index]->percentage_used >= m_perc_used_warn && m_formatter->has_format(FORMAT_WARN)) {
return FORMAT_WARN;
}
return FORMAT_MOUNTED;
}
/**
@ -155,24 +191,12 @@ namespace modules {
} else if (tag == TAG_BAR_USED) {
builder->node(m_barused->output(mount->percentage_used));
} else if (tag == TAG_RAMP_CAPACITY) {
builder->node(m_rampcapacity->get_by_percentage(mount->percentage_free));
builder->node(m_rampcapacity->get_by_percentage_with_borders(mount->percentage_free, 0, m_perc_used_warn));
} else if (tag == TAG_LABEL_MOUNTED) {
m_labelmounted->reset_tokens();
m_labelmounted->replace_token("%mountpoint%", mount->mountpoint);
m_labelmounted->replace_token("%type%", mount->type);
m_labelmounted->replace_token("%fsname%", mount->fsname);
m_labelmounted->replace_token("%percentage_free%", to_string(mount->percentage_free));
m_labelmounted->replace_token("%percentage_used%", to_string(mount->percentage_used));
m_labelmounted->replace_token(
"%total%", string_util::filesize(mount->bytes_total, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
m_labelmounted->replace_token(
"%free%", string_util::filesize(mount->bytes_avail, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
m_labelmounted->replace_token(
"%used%", string_util::filesize(mount->bytes_used, m_fixed ? 2 : 0, m_fixed, m_bar.locale));
builder->node(m_labelmounted);
} else if (tag == TAG_LABEL_WARN) {
builder->node(m_labelwarn);
} else if (tag == TAG_LABEL_UNMOUNTED) {
m_labelunmounted->reset_tokens();
m_labelunmounted->replace_token("%mountpoint%", mount->mountpoint);
builder->node(m_labelunmounted);
} else {
return false;

View File

@ -17,10 +17,19 @@ namespace modules {
memory_module::memory_module(const bar_settings& bar, string name_) : timer_module<memory_module>(bar, move(name_)) {
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
m_perc_memused_warn = m_conf.get(name(), "warn-percentage", 90);
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR_USED, TAG_BAR_FREE, TAG_RAMP_USED, TAG_RAMP_FREE,
TAG_BAR_SWAP_USED, TAG_BAR_SWAP_FREE, TAG_RAMP_SWAP_USED, TAG_RAMP_SWAP_FREE});
m_formatter->add_optional(FORMAT_WARN, {TAG_LABEL_WARN, TAG_BAR_USED, TAG_BAR_FREE, TAG_RAMP_USED, TAG_RAMP_FREE,
TAG_BAR_SWAP_USED, TAG_BAR_SWAP_FREE, TAG_RAMP_SWAP_USED, TAG_RAMP_SWAP_FREE});
if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%percentage_used%%");
}
if (m_formatter->has(TAG_LABEL_WARN)) {
m_labelwarn = load_optional_label(m_conf, name(), TAG_LABEL_WARN, "%percentage_used%%");
}
if (m_formatter->has(TAG_BAR_USED)) {
m_bar_memused = load_progressbar(m_bar, m_conf, name(), TAG_BAR_USED);
}
@ -45,10 +54,6 @@ namespace modules {
if(m_formatter->has(TAG_RAMP_SWAP_FREE)) {
m_ramp_swapfree = load_ramp(m_conf, name(), TAG_RAMP_SWAP_FREE);
}
if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%percentage_used%%");
}
}
bool memory_module::update() {
@ -96,29 +101,45 @@ namespace modules {
m_perc_swap_used = 100 - m_perc_swap_free;
// replace tokens
const auto replace_tokens = [&](label_t& label) {
label->reset_tokens();
label->replace_token("%gb_used%", string_util::filesize_gib(kb_total - kb_avail, 2, m_bar.locale));
label->replace_token("%gb_free%", string_util::filesize_gib(kb_avail, 2, m_bar.locale));
label->replace_token("%gb_total%", string_util::filesize_gib(kb_total, 2, m_bar.locale));
label->replace_token("%mb_used%", string_util::filesize_mib(kb_total - kb_avail, 0, m_bar.locale));
label->replace_token("%mb_free%", string_util::filesize_mib(kb_avail, 0, m_bar.locale));
label->replace_token("%mb_total%", string_util::filesize_mib(kb_total, 0, m_bar.locale));
label->replace_token("%percentage_used%", to_string(m_perc_memused));
label->replace_token("%percentage_free%", to_string(m_perc_memfree));
label->replace_token("%percentage_swap_used%", to_string(m_perc_swap_used));
label->replace_token("%percentage_swap_free%", to_string(m_perc_swap_free));
label->replace_token("%mb_swap_total%", string_util::filesize_mib(kb_swap_total, 0, m_bar.locale));
label->replace_token("%mb_swap_free%", string_util::filesize_mib(kb_swap_free, 0, m_bar.locale));
label->replace_token("%mb_swap_used%", string_util::filesize_mib(kb_swap_total - kb_swap_free, 0, m_bar.locale));
label->replace_token("%gb_swap_total%", string_util::filesize_gib(kb_swap_total, 2, m_bar.locale));
label->replace_token("%gb_swap_free%", string_util::filesize_gib(kb_swap_free, 2, m_bar.locale));
label->replace_token("%gb_swap_used%", string_util::filesize_gib(kb_swap_total - kb_swap_free, 2, m_bar.locale));
};
if (m_label) {
m_label->reset_tokens();
m_label->replace_token("%gb_used%", string_util::filesize_gib(kb_total - kb_avail, 2, m_bar.locale));
m_label->replace_token("%gb_free%", string_util::filesize_gib(kb_avail, 2, m_bar.locale));
m_label->replace_token("%gb_total%", string_util::filesize_gib(kb_total, 2, m_bar.locale));
m_label->replace_token("%mb_used%", string_util::filesize_mib(kb_total - kb_avail, 0, m_bar.locale));
m_label->replace_token("%mb_free%", string_util::filesize_mib(kb_avail, 0, m_bar.locale));
m_label->replace_token("%mb_total%", string_util::filesize_mib(kb_total, 0, m_bar.locale));
m_label->replace_token("%percentage_used%", to_string(m_perc_memused));
m_label->replace_token("%percentage_free%", to_string(m_perc_memfree));
m_label->replace_token("%percentage_swap_used%", to_string(m_perc_swap_used));
m_label->replace_token("%percentage_swap_free%", to_string(m_perc_swap_free));
m_label->replace_token("%mb_swap_total%", string_util::filesize_mib(kb_swap_total, 0, m_bar.locale));
m_label->replace_token("%mb_swap_free%", string_util::filesize_mib(kb_swap_free, 0, m_bar.locale));
m_label->replace_token("%mb_swap_used%", string_util::filesize_mib(kb_swap_total - kb_swap_free, 0, m_bar.locale));
m_label->replace_token("%gb_swap_total%", string_util::filesize_gib(kb_swap_total, 2, m_bar.locale));
m_label->replace_token("%gb_swap_free%", string_util::filesize_gib(kb_swap_free, 2, m_bar.locale));
m_label->replace_token("%gb_swap_used%", string_util::filesize_gib(kb_swap_total - kb_swap_free, 2, m_bar.locale));
replace_tokens(m_label);
}
if (m_labelwarn) {
replace_tokens(m_labelwarn);
}
return true;
}
string memory_module::get_format() const {
if (m_perc_memused>= m_perc_memused_warn && m_formatter->has_format(FORMAT_WARN)) {
return FORMAT_WARN;
} else {
return DEFAULT_FORMAT;
}
}
bool memory_module::build(builder* builder, const string& tag) const {
if (tag == TAG_BAR_USED) {
builder->node(m_bar_memused->output(m_perc_memused));
@ -126,18 +147,20 @@ namespace modules {
builder->node(m_bar_memfree->output(m_perc_memfree));
} else if (tag == TAG_LABEL) {
builder->node(m_label);
} else if (tag == TAG_LABEL_WARN) {
builder->node(m_labelwarn);
} else if (tag == TAG_RAMP_FREE) {
builder->node(m_ramp_memfree->get_by_percentage(m_perc_memfree));
builder->node(m_ramp_memfree->get_by_percentage_with_borders(m_perc_memfree, 0, m_perc_memused_warn));
} else if (tag == TAG_RAMP_USED) {
builder->node(m_ramp_memused->get_by_percentage(m_perc_memused));
builder->node(m_ramp_memused->get_by_percentage_with_borders(m_perc_memused, 0, m_perc_memused_warn));
} else if (tag == TAG_BAR_SWAP_USED) {
builder->node(m_bar_swapused->output(m_perc_swap_used));
} else if (tag == TAG_BAR_SWAP_FREE) {
builder->node(m_bar_swapfree->output(m_perc_swap_free));
} else if (tag == TAG_RAMP_SWAP_FREE) {
builder->node(m_ramp_swapfree->get_by_percentage(m_perc_swap_free));
builder->node(m_ramp_swapfree->get_by_percentage_with_borders(m_perc_swap_free, 0, m_perc_memused_warn));
} else if (tag == TAG_RAMP_SWAP_USED) {
builder->node(m_ramp_swapused->get_by_percentage(m_perc_swap_used));
builder->node(m_ramp_swapused->get_by_percentage_with_borders(m_perc_swap_used, 0, m_perc_memused_warn));
} else {
return false;
}

View File

@ -86,13 +86,12 @@ namespace modules {
// }}}
// module_formatter {{{
void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) {
const auto formatdef = [&](const string& param, const auto& fallback) {
return m_conf.get("settings", "format-" + param, fallback);
};
void module_formatter::add_value(string&& name, string&& value, vector<string>&& tags, vector<string>&& whitelist) {
const auto formatdef = [&](
const string& param, const auto& fallback) { return m_conf.get("settings", "format-" + param, fallback); };
auto format = make_unique<module_format>();
format->value = m_conf.get(m_modname, name, move(fallback));
format->value = move(value);
format->fg = m_conf.get(m_modname, name + "-foreground", formatdef("foreground", format->fg));
format->bg = m_conf.get(m_modname, name + "-background", formatdef("background", format->bg));
format->ul = m_conf.get(m_modname, name + "-underline", formatdef("underline", format->ul));
@ -124,7 +123,6 @@ namespace modules {
tag_collection.insert(tag_collection.end(), whitelist.begin(), whitelist.end());
size_t start, end;
string value{format->value};
while ((start = value.find('<')) != string::npos && (end = value.find('>', start)) != string::npos) {
if (start > 0) {
value.erase(0, start);
@ -141,6 +139,16 @@ namespace modules {
m_formats.insert(make_pair(move(name), move(format)));
}
void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) {
add_value(move(name), m_conf.get(m_modname, move(name), move(fallback)), forward<vector<string>>(tags), forward<vector<string>>(whitelist));
}
void module_formatter::add_optional(string name, vector<string>&& tags, vector<string>&& whitelist) {
if (m_conf.has(m_modname, name)) {
add_value(move(name), m_conf.get(m_modname, move(name)), move(tags), move(whitelist));
}
}
bool module_formatter::has(const string& tag, const string& format_name) {
auto format = m_formats.find(format_name);
if (format == m_formats.end()) {
@ -158,6 +166,10 @@ namespace modules {
return false;
}
bool module_formatter::has_format(const string& format_name) {
return m_formats.find(format_name) != m_formats.end();
}
shared_ptr<module_format> module_formatter::get(const string& format_name) {
auto format = m_formats.find(format_name);
if (format == m_formats.end()) {

View File

@ -53,7 +53,6 @@ namespace modules {
bool temperature_module::update() {
m_temp = std::strtol(file_util::contents(m_path).c_str(), nullptr, 10) / 1000.0f + 0.5f;
int temp_f = floor(((1.8 * m_temp) + 32) + 0.5);
m_perc = math_util::unbounded_percentage(m_temp, m_tempbase, m_tempwarn);
string temp_c_string = to_string(m_temp);
string temp_f_string = to_string(temp_f);
@ -97,7 +96,7 @@ namespace modules {
} else if (tag == TAG_LABEL_WARN) {
builder->node(m_label.at(temp_state::WARN));
} else if (tag == TAG_RAMP) {
builder->node(m_ramp->get_by_percentage_with_borders(m_perc));
builder->node(m_ramp->get_by_percentage_with_borders(m_temp, m_tempbase, m_tempwarn));
} else {
return false;
}

View File

@ -61,6 +61,7 @@ add_unit_test(components/bar)
add_unit_test(components/parser)
add_unit_test(components/config_parser)
add_unit_test(drawtypes/label)
add_unit_test(drawtypes/ramp)
add_unit_test(drawtypes/iconset)
# Run make check to build and run all unit tests

View File

@ -0,0 +1,25 @@
#include "common/test.hpp"
#include "drawtypes/ramp.hpp"
#include "utils/factory.hpp"
using namespace polybar::drawtypes;
using namespace polybar;
TEST(Ramp, perc) {
ramp r;
r.add(factory_util::shared<label>("test1", 0));
r.add(factory_util::shared<label>("test2", 0));
r.add(factory_util::shared<label>("test3", 0));
EXPECT_EQ("test1", r.get_by_percentage(33)->get());
EXPECT_EQ("test2", r.get_by_percentage(34)->get());
EXPECT_EQ("test3", r.get_by_percentage(67)->get());
EXPECT_EQ("test1", r.get_by_percentage_with_borders(19, 20, 40)->get());
EXPECT_EQ("test2", r.get_by_percentage_with_borders(21, 20, 40)->get());
EXPECT_EQ("test2", r.get_by_percentage_with_borders(39, 20, 40)->get());
EXPECT_EQ("test3", r.get_by_percentage_with_borders(41, 20, 40)->get());
EXPECT_EQ("test1", r.get_by_percentage_with_borders(20, 20, 40)->get());
EXPECT_EQ("test3", r.get_by_percentage_with_borders(40, 20, 40)->get());
r.add(factory_util::shared<label>("test4", 0));
EXPECT_EQ("test2", r.get_by_percentage_with_borders(29, 20, 40)->get());
EXPECT_EQ("test3", r.get_by_percentage_with_borders(31, 20, 40)->get());
}