mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-30 23:42:42 +01:00 
			
		
		
		
	Add a custom formatter for "pow" numbers. (#472)
Add a custom formatter for "pow" numbers.
This commit is contained in:
		| @@ -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(); | ||||
| }; | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Alex
					Alex