Skip to content

Commit 3131eb0

Browse files
authored
Add a custom formatter for "pow" numbers. (#472)
Add a custom formatter for "pow" numbers.
2 parents b3f9425 + f4d2ca2 commit 3131eb0

File tree

4 files changed

+104
-38
lines changed

4 files changed

+104
-38
lines changed

include/util/format.hpp

+78-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,84 @@
11
#pragma once
22

3-
#include <sstream>
3+
#include <fmt/format.h>
44

5-
namespace waybar::util {
5+
class pow_format {
6+
public:
7+
pow_format(long long val, std::string&& unit, bool binary = false):
8+
val_(val), unit_(unit), binary_(binary) { };
69

7-
std::string pow_format(unsigned long long value, const std::string &unit, bool binary = false);
10+
long long val_;
11+
std::string unit_;
12+
bool binary_;
13+
};
814

15+
16+
namespace fmt {
17+
template <>
18+
struct formatter<pow_format> {
19+
char spec = 0;
20+
int width = 0;
21+
22+
template <typename ParseContext>
23+
constexpr auto parse(ParseContext& ctx) -> decltype (ctx.begin()) {
24+
auto it = ctx.begin(), end = ctx.end();
25+
if (it != end && *it == ':') ++it;
26+
if (*it == '>' || *it == '<' || *it == '=') {
27+
spec = *it;
28+
++it;
29+
}
30+
if (it == end || *it == '}') return it;
31+
if ('0' <= *it && *it <= '9') {
32+
// We ignore it for now, but keep it for compatibility with
33+
// existing configs where the format for pow_format'ed numbers was
34+
// 'string' and specifications such as {:>9} were valid.
35+
// The rationale for ignoring it is that the only reason to specify
36+
// an alignment and a with is to get a fixed width bar, and ">" is
37+
// sufficient in this implementation.
38+
width = parse_nonnegative_int(it, end, ctx);
39+
}
40+
return it;
41+
}
42+
43+
template<class FormatContext>
44+
auto format(const pow_format& s, FormatContext &ctx) -> decltype (ctx.out()) {
45+
const char* units[] = { "", "k", "M", "G", "T", "P", nullptr};
46+
47+
auto base = s.binary_ ? 1024ull : 1000ll;
48+
auto fraction = (double) s.val_;
49+
50+
int pow;
51+
for (pow = 0; units[pow+1] != nullptr && fraction / base >= 1; ++pow) {
52+
fraction /= base;
53+
}
54+
55+
auto max_width = 4 // coeff in {:.3g} format
56+
+ 1 // prefix from units array
57+
+ s.binary_ // for the 'i' in GiB.
58+
+ s.unit_.length();
59+
60+
const char * format;
61+
std::string string;
62+
switch (spec) {
63+
case '>':
64+
return format_to(ctx.out(), "{:>{}}", fmt::format("{}", s), max_width);
65+
case '<':
66+
return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width);
67+
case '=':
68+
format = "{coefficient:<4.3g}{padding}{prefix}{unit}";
69+
break;
70+
case 0:
71+
default:
72+
format = "{coefficient:.3g}{prefix}{unit}";
73+
break;
74+
}
75+
return format_to(ctx.out(), format
76+
, fmt::arg("coefficient", fraction)
77+
, fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : ""))
78+
, fmt::arg("unit", s.unit_)
79+
, fmt::arg("padding", pow ? "" : s.binary_ ? " " : " ")
80+
);
81+
}
82+
};
983
}
84+

meson.build

-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ src_files = files(
9191
'src/modules/disk.cpp',
9292
'src/modules/idle_inhibitor.cpp',
9393
'src/modules/temperature.cpp',
94-
'src/util/format.cpp',
9594
'src/main.cpp',
9695
'src/bar.cpp',
9796
'src/client.cpp'

src/modules/disk.cpp

+26-8
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,33 @@ auto waybar::modules::Disk::update() -> void {
4444
return;
4545
}
4646

47-
label_.set_markup(fmt::format(format_,
48-
stats.f_bavail * 100 / stats.f_blocks,
49-
fmt::arg("free", pow_format(stats.f_bavail * stats.f_bsize, "B", true)),
50-
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
51-
fmt::arg("used", pow_format((stats.f_blocks - stats.f_bavail) * stats.f_bsize, "B", true)),
52-
fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
53-
));
47+
auto free = pow_format(stats.f_bavail * stats.f_bsize, "B", true);
48+
auto used = pow_format((stats.f_blocks - stats.f_bavail) * stats.f_bsize, "B", true);
49+
auto total = pow_format(stats.f_blocks * stats.f_bsize, "B", true);
50+
51+
label_.set_markup(fmt::format(format_
52+
, stats.f_bavail * 100 / stats.f_blocks
53+
, fmt::arg("free", free)
54+
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
55+
, fmt::arg("used", used)
56+
, fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
57+
, fmt::arg("total", total)
58+
, fmt::arg("path", path_)
59+
));
5460
if (tooltipEnabled()) {
55-
label_.set_tooltip_text(fmt::format("{} used", pow_format(stats.f_bavail * stats.f_bsize, "B", true)));
61+
std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)";
62+
if (config_["tooltip-format"].isString()) {
63+
tooltip_format = config_["tooltip-format"].asString();
64+
}
65+
label_.set_tooltip_text(fmt::format(tooltip_format
66+
, stats.f_bavail * 100 / stats.f_blocks
67+
, fmt::arg("free", free)
68+
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
69+
, fmt::arg("used", used)
70+
, fmt::arg("percentage_used", (stats.f_blocks - stats.f_bavail) * 100 / stats.f_blocks)
71+
, fmt::arg("total", total)
72+
, fmt::arg("path", path_)
73+
));
5674
}
5775
event_box_.show();
5876
}

src/util/format.cpp

-26
This file was deleted.

0 commit comments

Comments
 (0)