ISSUE#1877 Calendar week numbers
1. Let's do code simplier 2. Week format using regexp. Needs when user provide additional characters in format string and need to align week days according 3. Week format has got default formats: ":%U",":%V" 4. Week number is based on the first day of the week now. The output is the same as of date library now. 5. Avoiding of unnecessary operations
This commit is contained in:
parent
c5babb4c44
commit
57ad7f9536
|
@ -33,6 +33,8 @@ class Clock : public ALabel {
|
|||
|
||||
bool handleScroll(GdkEventScroll* e);
|
||||
|
||||
std::string weeks_format_;
|
||||
int weeks_format_left_gaps{0};
|
||||
auto calendar_text(const waybar_time& wtime) -> std::string;
|
||||
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
|
||||
auto first_day_of_week() -> date::weekday;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <type_traits>
|
||||
|
||||
#include "util/ustring_clen.hpp"
|
||||
|
@ -74,6 +75,13 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
|||
locale_ = std::locale("");
|
||||
}
|
||||
|
||||
if (config_["format-calendar-weeks"].isString()) {
|
||||
weeks_format_ = std::regex_replace(config_["format-calendar-weeks"].asString(), std::regex("\\{\\}"), (first_day_of_week() == date::Monday) ? "{:%V}" : "{:%U}");
|
||||
weeks_format_left_gaps = std::regex_replace(weeks_format_, std::regex(".*<b>|</b>.*|\\{.?+\\}"), "").length();
|
||||
} else {
|
||||
weeks_format_ = "";
|
||||
}
|
||||
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
@ -180,70 +188,63 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||
? date::day{0}
|
||||
: ymd.day()};
|
||||
const date::year_month ym{ymd.year(), ymd.month()};
|
||||
const auto weeks_format{config_["format-calendar-weeks"].isString()
|
||||
? config_["format-calendar-weeks"].asString()
|
||||
: ""};
|
||||
const auto first_dow = first_day_of_week();
|
||||
|
||||
std::stringstream os;
|
||||
|
||||
const date::weekday first_week_day = first_day_of_week();
|
||||
|
||||
enum class WeeksPlacement {
|
||||
enum class WeeksSide {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
HIDDEN,
|
||||
};
|
||||
WeeksPlacement weeks_pos = WeeksPlacement::HIDDEN;
|
||||
WeeksSide weeks_pos = WeeksSide::HIDDEN;
|
||||
|
||||
if (config_["calendar-weeks-pos"].isString()) {
|
||||
if (config_["calendar-weeks-pos"].asString() == "left") {
|
||||
weeks_pos = WeeksPlacement::LEFT;
|
||||
weeks_pos = WeeksSide::LEFT;
|
||||
// Add paddings before the header
|
||||
os << std::string(4, ' ');
|
||||
os << std::string(3 + weeks_format_left_gaps, ' ');
|
||||
} else if (config_["calendar-weeks-pos"].asString() == "right") {
|
||||
weeks_pos = WeeksPlacement::RIGHT;
|
||||
weeks_pos = WeeksSide::RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
weekdays_header(first_week_day, os);
|
||||
weekdays_header(first_dow, os);
|
||||
|
||||
// First week prefixed with spaces if needed.
|
||||
auto first_month_day = date::weekday(ym / 1);
|
||||
int empty_days = (first_week_day - first_month_day).count() + 1;
|
||||
date::sys_days last_week_day{static_cast<date::sys_days>(ym / 1) + date::days{7 - empty_days}};
|
||||
// First week day prefixed with spaces if needed.
|
||||
date::sys_days print_wd{ym/1};
|
||||
auto wd{date::weekday{print_wd}};
|
||||
auto empty_days = (wd - first_dow).count();
|
||||
|
||||
if (first_week_day == date::Monday) {
|
||||
last_week_day -= date::days{1};
|
||||
}
|
||||
/* Print weeknumber on the left for the first row*/
|
||||
if (weeks_pos == WeeksPlacement::LEFT) {
|
||||
os << fmt::format(weeks_format, date::format("%U", last_week_day)) << ' ';
|
||||
last_week_day += date::weeks{1};
|
||||
if (weeks_pos == WeeksSide::LEFT) {
|
||||
os << fmt::format(weeks_format_, print_wd) << ' ';
|
||||
}
|
||||
|
||||
if (empty_days > 0) {
|
||||
os << std::string(empty_days * 3 - 1, ' ');
|
||||
}
|
||||
|
||||
const auto last_day = (ym / date::literals::last).day();
|
||||
auto weekday = first_month_day;
|
||||
for (auto d = date::day(1); d <= last_day; ++d, ++weekday) {
|
||||
if (weekday != first_week_day) {
|
||||
|
||||
for (auto d{date::day{1}}; d <= last_day; ++d, ++wd) {
|
||||
if (wd != first_dow) {
|
||||
os << ' ';
|
||||
} else if (unsigned(d)!= 1) {
|
||||
last_week_day -= date::days{1};
|
||||
if (weeks_pos == WeeksPlacement::RIGHT) {
|
||||
os << ' ';
|
||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
||||
if (weeks_pos == WeeksSide::RIGHT) {
|
||||
os << ' ' << fmt::format(weeks_format_, print_wd);
|
||||
}
|
||||
|
||||
os << "\n";
|
||||
os << '\n';
|
||||
|
||||
if (weeks_pos == WeeksPlacement::LEFT) {
|
||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
||||
os << ' ';
|
||||
print_wd = {ym/d};
|
||||
|
||||
if (weeks_pos == WeeksSide::LEFT) {
|
||||
os << fmt::format(weeks_format_, print_wd) << ' ';
|
||||
}
|
||||
last_week_day += date::weeks{1} + date::days{1};
|
||||
}
|
||||
|
||||
if (d == curr_day) {
|
||||
if (config_["today-format"].isString()) {
|
||||
auto today_format = config_["today-format"].asString();
|
||||
|
@ -257,12 +258,13 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||
os << date::format("%e", d);
|
||||
}
|
||||
/*Print weeks on the right when the endings with spaces*/
|
||||
if (weeks_pos == WeeksPlacement::RIGHT && d == last_day) {
|
||||
last_week_day -= date::days{1};
|
||||
empty_days = 6 - (weekday - first_week_day).count();
|
||||
os << std::string(empty_days * 3 + 1, ' ');
|
||||
os << fmt::format(weeks_format, date::format("%U", last_week_day));
|
||||
last_week_day += date::days{1};
|
||||
if (weeks_pos == WeeksSide::RIGHT && d == last_day) {
|
||||
empty_days = 6 - (wd.c_encoding() - first_dow.c_encoding());
|
||||
if (empty_days > 0) {
|
||||
os << std::string(empty_days * 3, ' ');
|
||||
}
|
||||
|
||||
os << ' ' << fmt::format(weeks_format_, print_wd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +293,7 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_week_day
|
|||
const std::string pad(2 - clen, ' ');
|
||||
res << pad << wd_ustring;
|
||||
} while (++wd != first_week_day);
|
||||
res << "\n";
|
||||
res << '\n';
|
||||
|
||||
if (config_["format-calendar-weekdays"].isString()) {
|
||||
os << fmt::format(config_["format-calendar-weekdays"].asString(), res.str());
|
||||
|
@ -315,7 +317,7 @@ auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_poin
|
|||
timezone = date::current_zone();
|
||||
}
|
||||
wtime = {locale_, date::make_zoned(timezone, date::floor<std::chrono::seconds>(*now))};
|
||||
os << fmt::format(format_, wtime) << "\n";
|
||||
os << fmt::format(format_, wtime) << '\n';
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue