diff --git a/man/waybar-clock.5.scd b/man/waybar-clock.5.scd index e3213f39..6684d897 100644 --- a/man/waybar-clock.5.scd +++ b/man/waybar-clock.5.scd @@ -65,6 +65,10 @@ The *clock* module displays the current date and time. View all valid format options in *strftime(3)*. +# FORMAT REPLACEMENTS + +*{calendar}*: Current month calendar + # EXAMPLES ``` diff --git a/meson.build b/meson.build index 69439aca..812cc428 100644 --- a/meson.build +++ b/meson.build @@ -67,6 +67,7 @@ gtk_layer_shell = dependency('gtk-layer-shell-0', fallback : ['gtk-layer-shell', 'gtk_layer_shell_dep']) systemd = dependency('systemd', required: get_option('systemd')) tz_dep = dependency('date', default_options : [ 'use_system_tzdb=true' ], fallback: [ 'date', 'tz_dep' ]) +utfcpp = dependency('utfcpp', fallback: [ 'utfcpp', 'utfcpp_dep' ]) prefix = get_option('prefix') conf_data = configuration_data() @@ -168,7 +169,8 @@ executable( libudev, libmpdclient, gtk_layer_shell, - tz_dep + tz_dep, + utfcpp ], include_directories: [include_directories('include')], install: true, diff --git a/resources/config b/resources/config index 8dfa012b..116d377e 100644 --- a/resources/config +++ b/resources/config @@ -65,7 +65,7 @@ }, "clock": { // "timezone": "America/New_York", - "tooltip-format": "{:%Y-%m-%d | %H:%M}", + "tooltip-format": "{:%Y %B}\n{calendar}", "format-alt": "{:%Y-%m-%d}" }, "cpu": { diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 38af1152..f9181378 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -1,4 +1,86 @@ #include "modules/clock.hpp" +#include +#include + +using zoned_time = date::zoned_time; + +struct waybar_time { + std::locale locale; + zoned_time ztime; +}; + +namespace { + +size_t utf8_strlen(const std::string& s) { + return utf8::distance(s.begin(), s.end()); +} + +std::string utf8_substr(const std::string s, size_t len) { + utf8::iterator it(s.begin(), s.begin(), s.end()); + for (size_t i = 0; i < len; ++i) { + ++it; + } + int byte_count = it.base() - s.begin(); + return s.substr(0, byte_count); +} + +void weekdays_header(const std::locale& locale, const date::weekday& first_dow, std::ostream& os) { + auto wd = first_dow; + do { + if (wd != first_dow) os << ' '; + auto wd_string = date::format(locale, "%a", wd); + auto wd_string_len = utf8_strlen(wd_string); + if (wd_string_len > 2) { + wd_string = utf8_substr(wd_string, 2); + wd_string_len = 2; + } + const std::string pad(2 - wd_string_len, ' '); + os << pad << wd_string; + } while (++wd != first_dow); + os << "\n"; +} + +std::string calendar_text(const waybar_time& wtime, const date::weekday& first_dow) { + const auto daypoint = date::floor(wtime.ztime.get_local_time()); + const auto ymd = date::year_month_day(daypoint); + const date::year_month ym(ymd.year(), ymd.month()); + const auto curr_day = ymd.day(); + + std::stringstream os; + weekdays_header(wtime.locale, first_dow, os); + + // First week prefixed with spaces if needed. + auto wd = date::weekday(ym/1); + auto empty_days = (wd - first_dow).count(); + if (empty_days > 0) { + os << std::string(empty_days * 3 - 1, ' '); + } + auto d = date::day(1); + do { + if (wd != first_dow) os << ' '; + if (d == curr_day) { + os << "" << date::format("%e", d) << ""; + } else { + os << date::format("%e", d); + } + ++d; + } while (++wd != first_dow); + + // Following weeks. + auto last_day = (ym/date::literals::last).day(); + for ( ; d <= last_day; ++d, ++wd) { + os << ((wd == first_dow) ? '\n' : ' '); + if (d == curr_day) { + os << "" << date::format("%e", d) << ""; + } else { + os << date::format("%e", d); + } + } + + return os.str(); +} + +} waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) : ALabel(config, "clock", id, "{:%H:%M}", 60) @@ -24,13 +106,6 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) }; } -using zoned_time = date::zoned_time; - -struct waybar_time { - std::locale locale; - zoned_time ztime; -}; - auto waybar::modules::Clock::update() -> void { if (!fixed_time_zone_) { // Time zone can change. Be sure to pick that. @@ -44,11 +119,12 @@ auto waybar::modules::Clock::update() -> void { if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { + const auto calendar = calendar_text(wtime, date::Sunday); auto tooltip_format = config_["tooltip-format"].asString(); - auto tooltip_text = fmt::format(tooltip_format, wtime); - label_.set_tooltip_text(tooltip_text); + auto tooltip_text = fmt::format(tooltip_format, wtime, fmt::arg("calendar", calendar)); + label_.set_tooltip_markup(tooltip_text); } else { - label_.set_tooltip_text(text); + label_.set_tooltip_markup(text); } } } diff --git a/subprojects/utfcpp.wrap b/subprojects/utfcpp.wrap new file mode 100644 index 00000000..51cf131b --- /dev/null +++ b/subprojects/utfcpp.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = utfcpp-2.3.5 +source_url = https://github.com/nemtrif/utfcpp/archive/v2.3.5.zip +source_filename = utfcpp-2.3.5.zip +source_hash = 1d5cb7d908202d734ec35b84087400013f352ffb4612e978ffb948986b76df14 + +patch_url = https://github.com/mesonbuild/utfcpp/releases/download/2.3.5-1/utfcpp.zip +patch_filename = utfcpp-2.3.5-1-wrap.zip +patch_hash = 5f504de947b34bb5995fcdb66a1ea1392288076a9400ead829da79e73441a13f