From c0d84853ea2f3f8b016abf92458ba15378de6c91 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 18:09:44 -0800 Subject: [PATCH 1/6] refactor(clock): extract waybar_time to util/waybar_time.hpp --- include/modules/clock.hpp | 18 ++++++------------ include/util/waybar_time.hpp | 29 +++++++++++++++++++++++++++++ src/modules/clock.cpp | 14 ++------------ 3 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 include/util/waybar_time.hpp diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index 9f950192..ddcdf609 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -1,21 +1,14 @@ #pragma once -#include -#if FMT_VERSION < 60000 -#include -#else -#include -#endif #include #include "ALabel.hpp" #include "util/sleeper_thread.hpp" -namespace waybar::modules { +namespace waybar { -struct waybar_time { - std::locale locale; - date::zoned_seconds ztime; -}; +struct waybar_time; + +namespace modules { const std::string kCalendarPlaceholder = "calendar"; @@ -43,4 +36,5 @@ class Clock : public ALabel { bool is_timezone_fixed(); }; -} // namespace waybar::modules +} // namespace modules +} // namespace waybar diff --git a/include/util/waybar_time.hpp b/include/util/waybar_time.hpp new file mode 100644 index 00000000..3eaf1146 --- /dev/null +++ b/include/util/waybar_time.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#if FMT_VERSION < 60000 +#include +#else +#include +#endif +#include + +namespace waybar { + +struct waybar_time { + std::locale locale; + date::zoned_seconds ztime; +}; + +} // namespace waybar + +template <> +struct fmt::formatter : fmt::formatter { + template + auto format(const waybar::waybar_time& t, FormatContext& ctx) { +#if FMT_VERSION >= 80000 + auto& tm_format = specs; +#endif + return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(tm_format), t.ztime)); + } +}; diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 7e7d7420..739b79d1 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -6,12 +6,13 @@ #include #include #include "util/ustring_clen.hpp" +#include "util/waybar_time.hpp" #ifdef HAVE_LANGINFO_1STDAY #include #include #endif -using waybar::modules::waybar_time; +using waybar::waybar_time; waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true), @@ -227,14 +228,3 @@ auto waybar::modules::Clock::first_day_of_week() -> date::weekday { #endif return date::Sunday; } - -template <> -struct fmt::formatter : fmt::formatter { - template - auto format(const waybar_time& t, FormatContext& ctx) { -#if FMT_VERSION >= 80000 - auto& tm_format = specs; -#endif - return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(tm_format), t.ztime)); - } -}; From 8c41aaae046eb014b9192679f9c707fc429dbb9b Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 18:59:08 -0800 Subject: [PATCH 2/6] refactor(test): use single executable --- test/SafeSignal.cpp | 6 ------ test/config.cpp | 1 - test/main.cpp | 26 ++++++++++++++++++++++++++ test/meson.build | 23 ++++++----------------- 4 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 test/main.cpp diff --git a/test/SafeSignal.cpp b/test/SafeSignal.cpp index 2c67317b..244487f2 100644 --- a/test/SafeSignal.cpp +++ b/test/SafeSignal.cpp @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_RUNNER #include "util/SafeSignal.hpp" #include @@ -138,8 +137,3 @@ TEST_CASE_METHOD(GlibTestsFixture, "SafeSignal copy/move counter", "[signal][thr producer.join(); REQUIRE(count == NUM_EVENTS); } - -int main(int argc, char* argv[]) { - Glib::init(); - return Catch::Session().run(argc, argv); -} diff --git a/test/config.cpp b/test/config.cpp index edd6d6b8..29b0502a 100644 --- a/test/config.cpp +++ b/test/config.cpp @@ -1,4 +1,3 @@ -#define CATCH_CONFIG_MAIN #include "config.hpp" #include diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 00000000..bbfcc9f2 --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,26 @@ +#define CATCH_CONFIG_RUNNER +#include +#include +#include + +#include +#include +#include + +int main(int argc, char* argv[]) { + Catch::Session session; + Glib::init(); + + session.applyCommandLine(argc, argv); + const auto logger = spdlog::default_logger(); + const auto& reporter_name = session.config().getReporterName(); + if (reporter_name == "tap") { + spdlog::set_pattern("# [%l] %v"); + } else if (reporter_name == "compact") { + logger->sinks().clear(); + } else { + logger->sinks().assign({std::make_shared()}); + } + + return session.run(); +} diff --git a/test/meson.build b/test/meson.build index bbef21e7..473a6269 100644 --- a/test/meson.build +++ b/test/meson.build @@ -7,29 +7,18 @@ test_dep = [ spdlog, ] -config_test = executable( - 'config_test', +waybar_test = executable( + 'waybar_test', + 'main.cpp', + 'SafeSignal.cpp', 'config.cpp', '../src/config.cpp', dependencies: test_dep, include_directories: test_inc, ) -safesignal_test = executable( - 'safesignal_test', - 'SafeSignal.cpp', - dependencies: test_dep, - include_directories: test_inc, -) - test( - 'Configuration test', - config_test, - workdir: meson.source_root(), -) - -test( - 'SafeSignal test', - safesignal_test, + 'waybar', + waybar_test, workdir: meson.source_root(), ) From 766c8a103533828346577eab4be21aca49a83094 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 19:32:18 -0800 Subject: [PATCH 3/6] test: add tests for waybar_time formatter --- test/meson.build | 14 +++++-- test/waybar_time.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 test/waybar_time.cpp diff --git a/test/meson.build b/test/meson.build index 473a6269..b1e11237 100644 --- a/test/meson.build +++ b/test/meson.build @@ -6,13 +6,21 @@ test_dep = [ jsoncpp, spdlog, ] - -waybar_test = executable( - 'waybar_test', +test_src = files( 'main.cpp', 'SafeSignal.cpp', 'config.cpp', '../src/config.cpp', +) + +if tz_dep.found() + test_dep += tz_dep + test_src += files('waybar_time.cpp') +endif + +waybar_test = executable( + 'waybar_test', + test_src, dependencies: test_dep, include_directories: test_inc, ) diff --git a/test/waybar_time.cpp b/test/waybar_time.cpp new file mode 100644 index 00000000..5fc3312d --- /dev/null +++ b/test/waybar_time.cpp @@ -0,0 +1,90 @@ +#include "util/waybar_time.hpp" + +#include +#include + +#include +#include +#include + +using namespace std::literals::chrono_literals; + +/* + * Check that the date/time formatter with locale and timezone support is working as expected. + */ + +const date::zoned_time TEST_TIME = date::make_zoned( + "UTC", date::local_days{date::Monday[1] / date::January / 2022} + 13h + 4min + 5s); + +TEST_CASE("Format UTC time", "[clock][util]") { + waybar::waybar_time tm{std::locale("C"), TEST_TIME}; + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE(fmt::format("{:%c %Z}", tm) == "Mon Jan 3 13:04:05 2022 UTC"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405"); + + /* Test a few locales that are most likely to be present */ + SECTION("US locale") { + try { + tm.locale = std::locale("en_US"); + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE_THAT(fmt::format("{:%c}", tm), // HowardHinnant/date#704 + Catch::Matchers::StartsWith("Mon 03 Jan 2022 01:04:05 PM")); + REQUIRE(fmt::format("{:%x %X}", tm) == "01/03/2022 01:04:05 PM"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405"); + } catch (const std::runtime_error&) { + // locale not found; ignore + } + } + SECTION("GB locale") { + try { + tm.locale = std::locale("en_GB"); + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE_THAT(fmt::format("{:%c}", tm), // HowardHinnant/date#704 + Catch::Matchers::StartsWith("Mon 03 Jan 2022 13:04:05")); + REQUIRE(fmt::format("{:%x %X}", tm) == "03/01/22 13:04:05"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405"); + } catch (const std::runtime_error&) { + // locale not found; ignore + } + } +} + +TEST_CASE("Format zoned time", "[clock][util]") { + waybar::waybar_time tm{std::locale("C"), date::make_zoned("America/New_York", TEST_TIME)}; + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE(fmt::format("{:%c %Z}", tm) == "Mon Jan 3 08:04:05 2022 EST"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405"); + + /* Test a few locales that are most likely to be present */ + SECTION("US locale") { + try { + tm.locale = std::locale("en_US"); + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE_THAT(fmt::format("{:%c}", tm), // HowardHinnant/date#704 + Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05 AM")); + REQUIRE(fmt::format("{:%x %X}", tm) == "01/03/2022 08:04:05 AM"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405"); + } catch (const std::runtime_error&) { + // locale not found; ignore + } + } + + SECTION("GB locale") { + try { + tm.locale = std::locale("en_GB"); + + REQUIRE(fmt::format("{}", tm).empty()); // no format specified + REQUIRE_THAT(fmt::format("{:%c}", tm), // HowardHinnant/date#704 + Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05")); + REQUIRE(fmt::format("{:%x %X}", tm) == "03/01/22 08:04:05"); + REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405"); + } catch (const std::runtime_error&) { + // locale not found; ignore + } + } +} From 1489a539f85a177d5efe78a292fabfe9758a2f48 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 22:09:46 -0800 Subject: [PATCH 4/6] chore: bump supported fmt ver to 7.0.0 Certain features we use were added only in 7.0 and the code no longer compiles with any earlier versions. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 2c434266..1ccf6340 100644 --- a/meson.build +++ b/meson.build @@ -79,7 +79,7 @@ is_netbsd = host_machine.system() == 'netbsd' is_openbsd = host_machine.system() == 'openbsd' thread_dep = dependency('threads') -fmt = dependency('fmt', version : ['>=5.3.0'], fallback : ['fmt', 'fmt_dep']) +fmt = dependency('fmt', version : ['>=7.0.0'], fallback : ['fmt', 'fmt_dep']) spdlog = dependency('spdlog', version : ['>=1.8.5'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=true']) wayland_client = dependency('wayland-client') wayland_cursor = dependency('wayland-cursor') From 7f6bef20496ca23e83692801f6ff2957d28dde76 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 22:25:15 -0800 Subject: [PATCH 5/6] fix(util): make waybar_time formatter compatible with fmt 8.1.0 Stop using private implementation details of the `formatter`. We never needed anything from the class besides the format specifier, which is easily obtainable with public API. --- include/util/waybar_time.hpp | 32 +++++++++++++++++++++----------- src/modules/clock.cpp | 8 +++++++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/include/util/waybar_time.hpp b/include/util/waybar_time.hpp index 3eaf1146..c74e58c3 100644 --- a/include/util/waybar_time.hpp +++ b/include/util/waybar_time.hpp @@ -1,12 +1,7 @@ #pragma once -#include -#if FMT_VERSION < 60000 -#include -#else -#include -#endif #include +#include namespace waybar { @@ -18,12 +13,27 @@ struct waybar_time { } // namespace waybar template <> -struct fmt::formatter : fmt::formatter { +struct fmt::formatter { + std::string_view specs; + + template + constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + if (it != ctx.end() && *it == ':') { + ++it; + } + auto end = it; + while (end != ctx.end() && *end != '}') { + ++end; + } + if (end != it) { + specs = {it, std::string_view::size_type(end - it)}; + } + return end; + } + template auto format(const waybar::waybar_time& t, FormatContext& ctx) { -#if FMT_VERSION >= 80000 - auto& tm_format = specs; -#endif - return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(tm_format), t.ztime)); + return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(specs), t.ztime)); } }; diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 739b79d1..b0a6776a 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -1,10 +1,16 @@ #include "modules/clock.hpp" -#include #include +#if FMT_VERSION < 60000 +#include +#else +#include +#endif +#include #include #include + #include "util/ustring_clen.hpp" #include "util/waybar_time.hpp" #ifdef HAVE_LANGINFO_1STDAY From ce404199de0fb6cea8ff59cb8546c6669949a311 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Fri, 7 Jan 2022 22:50:23 -0800 Subject: [PATCH 6/6] chore: add `tzdata` to the alpine builder Fixes date formatting test execution on alpine. --- Dockerfiles/alpine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfiles/alpine b/Dockerfiles/alpine index c0e032ff..03836aaa 100644 --- a/Dockerfiles/alpine +++ b/Dockerfiles/alpine @@ -2,4 +2,4 @@ FROM alpine:latest -RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev pugixml-dev libnl3-dev pulseaudio-dev libmpdclient-dev sndio-dev scdoc libxkbcommon +RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev pugixml-dev libnl3-dev pulseaudio-dev libmpdclient-dev sndio-dev scdoc libxkbcommon tzdata