Merge pull request #4246 from edeustua/master

feat: Add ISO 8601 calendar to clock module
This commit is contained in:
Alexis Rouillard
2025-10-01 14:29:37 +02:00
committed by GitHub
3 changed files with 34 additions and 12 deletions

View File

@ -50,6 +50,7 @@ class Clock final : public ALabel {
std::string cldMonCached_; // calendar Month mode. Cached calendar std::string cldMonCached_; // calendar Month mode. Cached calendar
date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight) date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
std::string cldText_{""}; // calendar text to print std::string cldText_{""}; // calendar text to print
bool iso8601Calendar_{false}; // whether the calendar is in ISO8601
CldMode cldMode_{CldMode::MONTH}; CldMode cldMode_{CldMode::MONTH};
auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd, auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
const date::time_zone* tz) -> const std::string; const date::time_zone* tz) -> const std::string;

View File

@ -132,6 +132,12 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
:[ 1 :[ 1
:[ Value to scroll months/years forward/backward. Can be negative. Is :[ Value to scroll months/years forward/backward. Can be negative. Is
configured under *on-scroll* option configured under *on-scroll* option
|[ *iso8601*
:[ bool
:[ false
:[ When enabled, the calendar follows the ISO 8601 standard: weeks begin on
Monday, and the first week of the year is numbered 1. The default week format is
'{:%V}'.
3. Addressed by *clock: calendar: format* 3. Addressed by *clock: calendar: format*
[- *Option* [- *Option*

View File

@ -74,6 +74,11 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
"using instead", "using instead",
cfgMode); cfgMode);
} }
if (config_[kCldPlaceholder]["iso8601"].isBool()) {
iso8601Calendar_ = config_[kCldPlaceholder]["iso8601"].asBool();
}
if (config_[kCldPlaceholder]["weeks-pos"].isString()) { if (config_[kCldPlaceholder]["weeks-pos"].isString()) {
if (config_[kCldPlaceholder]["weeks-pos"].asString() == "left") cldWPos_ = WS::LEFT; if (config_[kCldPlaceholder]["weeks-pos"].asString() == "left") cldWPos_ = WS::LEFT;
if (config_[kCldPlaceholder]["weeks-pos"].asString() == "right") cldWPos_ = WS::RIGHT; if (config_[kCldPlaceholder]["weeks-pos"].asString() == "right") cldWPos_ = WS::RIGHT;
@ -98,17 +103,21 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
} else } else
fmtMap_.insert({3, "{}"}); fmtMap_.insert({3, "{}"});
if (config_[kCldPlaceholder]["format"]["weeks"].isString() && cldWPos_ != WS::HIDDEN) { if (config_[kCldPlaceholder]["format"]["weeks"].isString() && cldWPos_ != WS::HIDDEN) {
const auto defaultFmt =
iso8601Calendar_ ? "{:%V}" : ((first_day_of_week() == Monday) ? "{:%W}" : "{:%U}");
fmtMap_.insert({4, std::regex_replace(config_[kCldPlaceholder]["format"]["weeks"].asString(), fmtMap_.insert({4, std::regex_replace(config_[kCldPlaceholder]["format"]["weeks"].asString(),
std::regex("\\{\\}"), std::regex("\\{\\}"), defaultFmt)});
(first_day_of_week() == Monday) ? "{:%W}" : "{:%U}")});
Glib::ustring tmp{std::regex_replace(fmtMap_[4], std::regex("</?[^>]+>|\\{.*\\}"), "")}; Glib::ustring tmp{std::regex_replace(fmtMap_[4], std::regex("</?[^>]+>|\\{.*\\}"), "")};
cldWnLen_ += tmp.size(); cldWnLen_ += tmp.size();
} else { } else {
if (cldWPos_ != WS::HIDDEN) if (cldWPos_ != WS::HIDDEN) {
fmtMap_.insert({4, (first_day_of_week() == Monday) ? "{:%W}" : "{:%U}"}); const auto defaultFmt =
else iso8601Calendar_ ? "{:%V}" : ((first_day_of_week() == Monday) ? "{:%W}" : "{:%U}");
fmtMap_.insert({4, defaultFmt});
} else {
cldWnLen_ = 0; cldWnLen_ = 0;
} }
}
if (config_[kCldPlaceholder]["mode-mon-col"].isInt()) { if (config_[kCldPlaceholder]["mode-mon-col"].isInt()) {
cldMonCols_ = config_[kCldPlaceholder]["mode-mon-col"].asInt(); cldMonCols_ = config_[kCldPlaceholder]["mode-mon-col"].asInt();
if (cldMonCols_ == 0u || (12 % cldMonCols_) != 0u) { if (cldMonCols_ == 0u || (12 % cldMonCols_) != 0u) {
@ -218,9 +227,11 @@ const unsigned cldRowsInMonth(const year_month& ym, const weekday& firstdow) {
auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow, const unsigned line) auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow, const unsigned line)
-> const year_month_weekday { -> const year_month_weekday {
unsigned index{line - 2}; const unsigned idx = line - 2;
if (weekday{ym / 1} == firstdow) ++index; const std::chrono::weekday_indexed indexed_first_day_of_week =
return ym / firstdow[index]; weekday{ym / 1} == firstdow ? firstdow[idx + 1] : firstdow[idx];
return ym / indexed_first_day_of_week;
} }
auto getCalendarLine(const year_month_day& currDate, const year_month ym, const unsigned line, auto getCalendarLine(const year_month_day& currDate, const year_month ym, const unsigned line,
@ -279,7 +290,7 @@ auto getCalendarLine(const year_month_day& currDate, const year_month ym, const
} }
// Print non-first week // Print non-first week
default: { default: {
auto ymdTmp{cldGetWeekForLine(ym, firstdow, line)}; const auto ymdTmp{cldGetWeekForLine(ym, firstdow, line)};
if (ymdTmp.ok()) { if (ymdTmp.ok()) {
auto d{year_month_day{ymdTmp}.day()}; auto d{year_month_day{ymdTmp}.day()};
const auto dlast{(ym / last).day()}; const auto dlast{(ym / last).day()};
@ -370,10 +381,11 @@ auto waybar::modules::Clock::get_calendar(const year_month_day& today, const yea
: static_cast<const zoned_seconds&&>(zoned_seconds{ : static_cast<const zoned_seconds&&>(zoned_seconds{
tz, local_days{cldGetWeekForLine(ymTmp, firstdow, line)}}))) tz, local_days{cldGetWeekForLine(ymTmp, firstdow, line)}})))
<< ' '; << ' ';
} else } else {
os << pads; os << pads;
} }
} }
}
// Count wide characters to avoid extra padding // Count wide characters to avoid extra padding
size_t wideCharCount = 0; size_t wideCharCount = 0;
@ -495,6 +507,9 @@ using deleting_unique_ptr = std::unique_ptr<T, deleter_from_fn<fn>>;
// Computations done similarly to Linux cal utility. // Computations done similarly to Linux cal utility.
auto waybar::modules::Clock::first_day_of_week() -> weekday { auto waybar::modules::Clock::first_day_of_week() -> weekday {
if (iso8601Calendar_) {
return Monday;
}
#ifdef HAVE_LANGINFO_1STDAY #ifdef HAVE_LANGINFO_1STDAY
deleting_unique_ptr<std::remove_pointer<locale_t>::type, freelocale> posix_locale{ deleting_unique_ptr<std::remove_pointer<locale_t>::type, freelocale> posix_locale{
newlocale(LC_ALL, m_locale_.name().c_str(), nullptr)}; newlocale(LC_ALL, m_locale_.name().c_str(), nullptr)};