aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-09-22 18:56:44 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-09-22 18:56:44 +0200
commit22f6534081acfabdab4956d337604a21e7da5b64 (patch)
treea857b256a120d154667f2ed68cbf5151afe0cfbf
parent676586f2034ff112b309dccc430893d73e919191 (diff)
downloadttwhy-22f6534081acfabdab4956d337604a21e7da5b64.tar.xz
ttwhy-22f6534081acfabdab4956d337604a21e7da5b64.zip
lib: generalize concepts
-rw-r--r--ttwhy/io/readers.cppm6
-rw-r--r--ttwhy/routers/concepts.cppm7
-rw-r--r--ttwhy/routers/echo.cppm2
-rw-r--r--ttwhy/routers/echo.tests.cpp20
-rw-r--r--ttwhy/scanners/concepts.cppm13
-rw-r--r--ttwhy/scanners/terminal_policies.cppm18
-rw-r--r--ttwhy/scanners/terminal_scanner.cppm6
7 files changed, 33 insertions, 39 deletions
diff --git a/ttwhy/io/readers.cppm b/ttwhy/io/readers.cppm
index d15cc7a..56ce2b0 100644
--- a/ttwhy/io/readers.cppm
+++ b/ttwhy/io/readers.cppm
@@ -16,7 +16,8 @@ import ttwhy.scanners;
namespace ttwhy::io
{
- export template<typename InputStream, router AppRouter>
+ export template<typename TerminalPolicy = scanners::xterm_policy, typename InputStream,
+ router<scanners::input_event> AppRouter>
auto read_events(InputStream & stream, AppRouter & router) -> asio::awaitable<void>
{
using namespace asio::experimental::awaitable_operators;
@@ -32,8 +33,7 @@ namespace ttwhy::io
queue.push_back(event);
};
- using terminal_policy = ttwhy::scanners::associated_terminal_policy_t<AppRouter>;
- auto scanner = scanners::terminal_scanner<decltype(sink), terminal_policy>{sink};
+ auto scanner = scanners::terminal_scanner<decltype(sink), TerminalPolicy>{sink};
auto raw_buffer = std::array<char, 64>{};
diff --git a/ttwhy/routers/concepts.cppm b/ttwhy/routers/concepts.cppm
index 9660afc..cfbcb5a 100644
--- a/ttwhy/routers/concepts.cppm
+++ b/ttwhy/routers/concepts.cppm
@@ -6,14 +6,11 @@ module;
export module ttwhy.routers:concepts;
-import ttwhy.scanners;
-
namespace ttwhy
{
- export template<typename Candidate>
- concept router = requires(Candidate candidate, scanners::input_event event) {
- typename Candidate::terminal_policy;
+ export template<typename Candidate, typename Event>
+ concept router = requires(Candidate candidate, Event event) {
{ candidate.process(event) } -> std::same_as<asio::awaitable<void>>;
};
diff --git a/ttwhy/routers/echo.cppm b/ttwhy/routers/echo.cppm
index ff309c8..c9cd7c7 100644
--- a/ttwhy/routers/echo.cppm
+++ b/ttwhy/routers/echo.cppm
@@ -29,8 +29,6 @@ namespace ttwhy::routers
export template<typename StreamType>
struct echo
{
- using terminal_policy = scanners::xterm_policy;
-
explicit echo(StreamType & stream)
: m_output_stream{stream}
{}
diff --git a/ttwhy/routers/echo.tests.cpp b/ttwhy/routers/echo.tests.cpp
index c6ea10a..da2db40 100644
--- a/ttwhy/routers/echo.tests.cpp
+++ b/ttwhy/routers/echo.tests.cpp
@@ -46,29 +46,27 @@ namespace
}
};
- struct incomplete_router_no_policy
- {
- auto process(ttwhy::scanners::input_event) -> asio::awaitable<void>;
- };
-
struct incomplete_router_no_process
{
- using terminal_policy = ttwhy::scanners::xterm_policy;
};
struct incomplete_router_wrong_return
{
- using terminal_policy = ttwhy::scanners::xterm_policy;
auto process(ttwhy::scanners::input_event) -> void;
};
+
+ struct incomplete_router_wrong_event
+ {
+ auto process(int) -> asio::awaitable<void>;
+ };
} // namespace
TEST_CASE("The router concept validates router candidate interfaces", "[router][concept]")
{
- STATIC_REQUIRE(ttwhy::router<ttwhy::routers::echo<mock_stream>>);
- STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_no_policy>);
- STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_no_process>);
- STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_wrong_return>);
+ STATIC_REQUIRE(ttwhy::router<ttwhy::routers::echo<mock_stream>, ttwhy::scanners::input_event>);
+ STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_no_process, ttwhy::scanners::input_event>);
+ STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_wrong_return, ttwhy::scanners::input_event>);
+ STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_wrong_event, ttwhy::scanners::input_event>);
}
SCENARIO("The echo router handles terminal navigation within the valid printed area", "[router][echo]")
diff --git a/ttwhy/scanners/concepts.cppm b/ttwhy/scanners/concepts.cppm
index 69d6459..5c29b5f 100644
--- a/ttwhy/scanners/concepts.cppm
+++ b/ttwhy/scanners/concepts.cppm
@@ -17,11 +17,14 @@ namespace ttwhy
{ a.is_pending() } -> std::same_as<bool>;
};
- export template<typename Sink>
- concept ansi_sink = requires(Sink sink) {
- { sink(std::declval<ttwhy::scanners::character_event>()) } -> std::same_as<void>;
- { sink(std::declval<ttwhy::scanners::control_event>()) } -> std::same_as<void>;
- { sink(std::declval<ttwhy::scanners::navigation_event>()) } -> std::same_as<void>;
+ export template<typename Sink, typename Event>
+ concept event_sink = requires(Sink sink, Event event) {
+ { sink(event) } -> std::same_as<void>;
};
+ export template<typename Sink>
+ concept terminal_event_sink =
+ event_sink<Sink, scanners::character_event> && event_sink<Sink, scanners::control_event> &&
+ event_sink<Sink, scanners::navigation_event>;
+
} // namespace ttwhy
diff --git a/ttwhy/scanners/terminal_policies.cppm b/ttwhy/scanners/terminal_policies.cppm
index 7af0d66..e3c889c 100644
--- a/ttwhy/scanners/terminal_policies.cppm
+++ b/ttwhy/scanners/terminal_policies.cppm
@@ -59,12 +59,9 @@ namespace ttwhy::scanners
} // namespace detail
- export template<typename T>
- using associated_terminal_policy_t = typename T::terminal_policy;
-
export struct ansi_policy
{
- constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::ansi_sink auto & sink) -> void
+ constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::terminal_event_sink auto & sink) -> void
{
if (buffer.empty())
{
@@ -78,7 +75,8 @@ namespace ttwhy::scanners
buffer.clear();
}
- constexpr auto static resolve_vt100_cursor(char terminator, std::string &, ttwhy::ansi_sink auto & sink) -> void
+ constexpr auto static resolve_vt100_cursor(char terminator, std::string &, ttwhy::terminal_event_sink auto & sink)
+ -> void
{
if (auto key = detail::map_vt100_cursor(terminator))
{
@@ -86,7 +84,7 @@ namespace ttwhy::scanners
}
}
- constexpr auto static resolve_ss3(char terminator, ttwhy::ansi_sink auto & sink) -> void
+ constexpr auto static resolve_ss3(char terminator, ttwhy::terminal_event_sink auto & sink) -> void
{
if (auto key = detail::map_vt100_cursor(terminator))
{
@@ -124,7 +122,7 @@ namespace ttwhy::scanners
return static_cast<modifier_set>(modifier_value - 1);
}
- constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::ansi_sink auto & sink) -> void
+ constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::terminal_event_sink auto & sink) -> void
{
if (buffer.empty())
{
@@ -140,8 +138,8 @@ namespace ttwhy::scanners
buffer.clear();
}
- constexpr auto static resolve_vt100_cursor(char terminator, std::string & buffer, ttwhy::ansi_sink auto & sink)
- -> void
+ constexpr auto static resolve_vt100_cursor(char terminator, std::string & buffer,
+ ttwhy::terminal_event_sink auto & sink) -> void
{
auto modifiers = parse_modifiers(buffer);
@@ -151,7 +149,7 @@ namespace ttwhy::scanners
}
}
- constexpr auto static resolve_ss3(char terminator, ttwhy::ansi_sink auto & sink) -> void
+ constexpr auto static resolve_ss3(char terminator, ttwhy::terminal_event_sink auto & sink) -> void
{
if (auto key = detail::map_vt100_cursor(terminator))
{
diff --git a/ttwhy/scanners/terminal_scanner.cppm b/ttwhy/scanners/terminal_scanner.cppm
index ec4a1a6..a791909 100644
--- a/ttwhy/scanners/terminal_scanner.cppm
+++ b/ttwhy/scanners/terminal_scanner.cppm
@@ -95,7 +95,7 @@ namespace ttwhy::scanners::detail
/// Transitions
- template<ansi_sink Sink, typename TerminalPolicy>
+ template<terminal_event_sink Sink, typename TerminalPolicy>
struct transition_table
{
auto operator()() const noexcept
@@ -200,7 +200,7 @@ namespace ttwhy::scanners::detail
export namespace ttwhy::scanners
{
- template<ansi_sink Sink, typename TerminalPolicy>
+ template<terminal_event_sink Sink, typename TerminalPolicy>
struct terminal_scanner
{
explicit terminal_scanner(Sink & sink)
@@ -230,7 +230,7 @@ export namespace ttwhy::scanners
m_state_machine;
};
- template<ansi_sink Sink>
+ template<terminal_event_sink Sink>
using ansi = terminal_scanner<Sink, ansi_policy>;
} // namespace ttwhy::scanners