Add a custom formatter for "pow" numbers. (#472)
Add a custom formatter for "pow" numbers.
This commit is contained in:
commit
3131eb0774
|
@ -1,9 +1,84 @@
|
|||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace waybar::util {
|
||||
class pow_format {
|
||||
public:
|
||||
pow_format(long long val, std::string&& unit, bool binary = false):
|
||||
val_(val), unit_(unit), binary_(binary) { };
|
||||
|
||||
std::string pow_format(unsigned long long value, const std::string &unit, bool binary = false);
|
||||
long long val_;
|
||||
std::string unit_;
|
||||
bool binary_;
|
||||
};
|
||||
|
||||
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<pow_format> {
|
||||
char spec = 0;
|
||||
int width = 0;
|
||||
|
||||
template <typename ParseContext>
|
||||
constexpr auto parse(ParseContext& ctx) -> decltype (ctx.begin()) {
|
||||
auto it = ctx.begin(), end = ctx.end();
|
||||
if (it != end && *it == ':') ++it;
|
||||
if (*it == '>' || *it == '<' || *it == '=') {
|
||||
spec = *it;
|
||||
++it;
|
||||
}
|
||||
if (it == end || *it == '}') return it;
|
||||
if ('0' <= *it && *it <= '9') {
|
||||
// We ignore it for now, but keep it for compatibility with
|
||||
// existing configs where the format for pow_format'ed numbers was
|
||||
// 'string' and specifications such as {:>9} were valid.
|
||||
// The rationale for ignoring it is that the only reason to specify
|
||||
// an alignment and a with is to get a fixed width bar, and ">" is
|
||||
// sufficient in this implementation.
|
||||
width = parse_nonnegative_int(it, end, ctx);
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
template<class FormatContext>
|
||||
auto format(const pow_format& s, FormatContext &ctx) -> decltype (ctx.out()) {
|
||||
const char* units[] = { "", "k", "M", "G", "T", "P", nullptr};
|
||||
|
||||
auto base = s.binary_ ? 1024ull : 1000ll;
|
||||
auto fraction = (double) s.val_;
|
||||
|
||||
int pow;
|
||||
for (pow = 0; units[pow+1] != nullptr && fraction / base >= 1; ++pow) {
|
||||
fraction /= base;
|
||||
}
|
||||
|
||||
auto max_width = 4 // coeff in {:.3g} format
|
||||
+ 1 // prefix from units array
|
||||
+ s.binary_ // for the 'i' in GiB.
|
||||
+ s.unit_.length();
|
||||
|
||||
const char * format;
|
||||
std::string string;
|
||||
switch (spec) {
|
||||
case '>':
|
||||
return format_to(ctx.out(), "{:>{}}", fmt::format("{}", s), max_width);
|
||||
case '<':
|
||||
return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width);
|
||||
case '=':
|
||||
format = "{coefficient:<4.3g}{padding}{prefix}{unit}";
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
format = "{coefficient:.3g}{prefix}{unit}";
|
||||
break;
|
||||
}
|
||||
return format_to(ctx.out(), format
|
||||
, fmt::arg("coefficient", fraction)
|
||||
, fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : ""))
|
||||
, fmt::arg("unit", s.unit_)
|
||||
, fmt::arg("padding", pow ? "" : s.binary_ ? " " : " ")
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ src_files = files(
|
|||
'src/modules/disk.cpp',
|
||||
'src/modules/idle_inhibitor.cpp',
|
||||
'src/modules/temperature.cpp',
|
||||
'src/util/format.cpp',
|
||||
'src/main.cpp',
|
||||
'src/bar.cpp',
|
||||
'src/client.cpp'
|
||||
|
|
|
@ -44,15 +44,33 @@ auto waybar::modules::Disk::update() -> void {
|
|||
return;
|
||||
}
|
||||
|
||||
label_.set_markup(fmt::format(format_,
|
||||
stats.f_bavail * 100 / stats.f_blocks,
|
||||
fmt::arg("free", pow_format(stats.f_bavail * stats.f_bsize, "B", true)),
|
||||
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
|
||||
fmt::arg("used", pow_format((stats.f_blocks - stats.f_bavail) * stats.f_bsize, "B", true)),
|
||||
fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
|
||||
auto free = pow_format(stats.f_bavail * stats.f_bsize, "B", true);
|
||||
auto used = pow_format((stats.f_blocks - stats.f_bavail) * stats.f_bsize, "B", true);
|
||||
auto total = pow_format(stats.f_blocks * stats.f_bsize, "B", true);
|
||||
|
||||
label_.set_markup(fmt::format(format_
|
||||
, stats.f_bavail * 100 / stats.f_blocks
|
||||
, fmt::arg("free", free)
|
||||
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
|
||||
, fmt::arg("used", used)
|
||||
, fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
|
||||
, fmt::arg("total", total)
|
||||
, fmt::arg("path", path_)
|
||||
));
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(fmt::format("{} used", pow_format(stats.f_bavail * stats.f_bsize, "B", true)));
|
||||
std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)";
|
||||
if (config_["tooltip-format"].isString()) {
|
||||
tooltip_format = config_["tooltip-format"].asString();
|
||||
}
|
||||
label_.set_tooltip_text(fmt::format(tooltip_format
|
||||
, stats.f_bavail * 100 / stats.f_blocks
|
||||
, fmt::arg("free", free)
|
||||
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
|
||||
, fmt::arg("used", used)
|
||||
, fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
|
||||
, fmt::arg("total", total)
|
||||
, fmt::arg("path", path_)
|
||||
));
|
||||
}
|
||||
event_box_.show();
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#include <sstream>
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
std::string pow_format(unsigned long long value, const std::string &unit, bool binary = false) {
|
||||
auto base = binary ? 1024ull : 1000ull;
|
||||
const char* units[] = { "", "k", "M", "G", "T", "P", nullptr};
|
||||
auto fraction = (double) value;
|
||||
|
||||
int pow;
|
||||
for (pow = 0; units[pow+1] != nullptr && fraction / base >= 2; ++pow) {
|
||||
fraction /= base;
|
||||
}
|
||||
|
||||
std::ostringstream ss;
|
||||
if (pow > 0) {
|
||||
auto quotient = (unsigned long long) fraction;
|
||||
auto remainder = (unsigned long long) ((fraction - quotient) * 10);
|
||||
ss << quotient << "." << remainder << units[pow] << (binary ? "i" : "") << unit;
|
||||
} else {
|
||||
ss << value << unit;
|
||||
}
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue