diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-09-22 22:47:33 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-09-22 22:47:33 +0200 |
| commit | d05b9343f69a0841043963088e0003368e205bd9 (patch) | |
| tree | 8cde07ff86d27cbc808a0a149b89d0024b4a586c | |
| parent | 22f6534081acfabdab4956d337604a21e7da5b64 (diff) | |
| download | ttwhy-master.tar.xz ttwhy-master.zip | |
| -rw-r--r-- | CMakeLists.txt | 29 | ||||
| -rw-r--r-- | apps/echo.cpp | 11 | ||||
| -rw-r--r-- | ttwhy/core/concepts.cppm (renamed from ttwhy/scanners/concepts.cppm) | 16 | ||||
| -rw-r--r-- | ttwhy/core/mod.cppm | 3 | ||||
| -rw-r--r-- | ttwhy/io/mod.cppm | 5 | ||||
| -rw-r--r-- | ttwhy/lib.cppm | 5 | ||||
| -rw-r--r-- | ttwhy/routers/concepts.cppm | 17 | ||||
| -rw-r--r-- | ttwhy/routers/mod.cppm | 4 | ||||
| -rw-r--r-- | ttwhy/scanners/mod.cppm | 6 | ||||
| -rw-r--r-- | ttwhy/terminal/echo.cppm (renamed from ttwhy/routers/echo.cppm) | 37 | ||||
| -rw-r--r-- | ttwhy/terminal/echo.tests.cpp (renamed from ttwhy/routers/echo.tests.cpp) | 50 | ||||
| -rw-r--r-- | ttwhy/terminal/events.cppm (renamed from ttwhy/scanners/terminal_events.cppm) | 13 | ||||
| -rw-r--r-- | ttwhy/terminal/mod.cppm | 9 | ||||
| -rw-r--r-- | ttwhy/terminal/policies.cppm (renamed from ttwhy/scanners/terminal_policies.cppm) | 23 | ||||
| -rw-r--r-- | ttwhy/terminal/readers.cppm (renamed from ttwhy/io/readers.cppm) | 19 | ||||
| -rw-r--r-- | ttwhy/terminal/scanner.cppm (renamed from ttwhy/scanners/terminal_scanner.cppm) | 28 | ||||
| -rw-r--r-- | ttwhy/terminal/scanner.tests.cpp (renamed from ttwhy/scanners/terminal_scanner.tests.cpp) | 27 | ||||
| -rw-r--r-- | ttwhy/terminal/scoped_attributes.cppm (renamed from ttwhy/io/scoped_attributes.cppm) | 6 | ||||
| -rw-r--r-- | ttwhy/terminal/signal_handling.cppm (renamed from ttwhy/io/signal_handling.cppm) | 6 |
19 files changed, 148 insertions, 166 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 337086f..bdda024 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,20 +65,17 @@ target_sources("ttwhy-core" PUBLIC "ttwhy/lib.cppm" - "ttwhy/io/mod.cppm" - "ttwhy/io/readers.cppm" - "ttwhy/io/scoped_attributes.cppm" - "ttwhy/io/signal_handling.cppm" - - "ttwhy/routers/mod.cppm" - "ttwhy/routers/concepts.cppm" - "ttwhy/routers/echo.cppm" - - "ttwhy/scanners/mod.cppm" - "ttwhy/scanners/concepts.cppm" - "ttwhy/scanners/terminal_events.cppm" - "ttwhy/scanners/terminal_policies.cppm" - "ttwhy/scanners/terminal_scanner.cppm" + "ttwhy/core/mod.cppm" + "ttwhy/core/concepts.cppm" + + "ttwhy/terminal/mod.cppm" + "ttwhy/terminal/echo.cppm" + "ttwhy/terminal/events.cppm" + "ttwhy/terminal/policies.cppm" + "ttwhy/terminal/readers.cppm" + "ttwhy/terminal/scanner.cppm" + "ttwhy/terminal/scoped_attributes.cppm" + "ttwhy/terminal/signal_handling.cppm" ) @@ -122,8 +119,8 @@ if(BUILD_TESTING) add_executable("ttwhy::tests" ALIAS "ttwhy-tests") target_sources("ttwhy-tests" PRIVATE - "ttwhy/routers/echo.tests.cpp" - "ttwhy/scanners/terminal_scanner.tests.cpp" + "ttwhy/terminal/echo.tests.cpp" + "ttwhy/terminal/scanner.tests.cpp" ) target_link_libraries("ttwhy-tests" PRIVATE diff --git a/apps/echo.cpp b/apps/echo.cpp index ab635a7..c13ef92 100644 --- a/apps/echo.cpp +++ b/apps/echo.cpp @@ -3,14 +3,13 @@ #include <stdio.h> -import ttwhy.io; -import ttwhy.routers; +import ttwhy.terminal; auto app(int in, int out, int error) -> asio::awaitable<void> { using namespace asio::experimental::awaitable_operators; - auto terminal_attributes = ttwhy::io::scoped_attributes{fileno(stdin)} // + auto terminal_attributes = ttwhy::terminal::scoped_attributes{fileno(stdin)} // .canonical_mode(false) .echo(false); @@ -20,10 +19,10 @@ auto app(int in, int out, int error) -> asio::awaitable<void> auto output_stream = asio::posix::stream_descriptor{executor, out}; auto error_stream = asio::posix::stream_descriptor{executor, error}; - auto router = ttwhy::routers::echo{output_stream}; + auto router = ttwhy::terminal::echo{output_stream}; - co_await (ttwhy::io::handle_signals(error_stream, terminal_attributes) || - ttwhy::io::read_events(input_stream, router)); + co_await (ttwhy::terminal::handle_signals(error_stream, terminal_attributes) || + ttwhy::terminal::read_events(input_stream, router)); } auto main() -> int diff --git a/ttwhy/scanners/concepts.cppm b/ttwhy/core/concepts.cppm index 5c29b5f..f7ac583 100644 --- a/ttwhy/scanners/concepts.cppm +++ b/ttwhy/core/concepts.cppm @@ -1,11 +1,11 @@ module; +#include <asio.hpp> + #include <concepts> #include <span> -export module ttwhy.scanners:concepts; - -import :terminal_events; +export module ttwhy.core:concepts; namespace ttwhy { @@ -17,14 +17,14 @@ namespace ttwhy { a.is_pending() } -> std::same_as<bool>; }; + export template<typename Candidate, typename Event> + concept router = requires(Candidate candidate, Event event) { + { candidate.process(event) } -> std::same_as<asio::awaitable<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/core/mod.cppm b/ttwhy/core/mod.cppm new file mode 100644 index 0000000..a6bf056 --- /dev/null +++ b/ttwhy/core/mod.cppm @@ -0,0 +1,3 @@ +export module ttwhy.core; + +export import :concepts; diff --git a/ttwhy/io/mod.cppm b/ttwhy/io/mod.cppm deleted file mode 100644 index 8deff38..0000000 --- a/ttwhy/io/mod.cppm +++ /dev/null @@ -1,5 +0,0 @@ -export module ttwhy.io; - -export import :readers; -export import :scoped_attributes; -export import :signal_handling; diff --git a/ttwhy/lib.cppm b/ttwhy/lib.cppm index 474d6b4..158dcda 100644 --- a/ttwhy/lib.cppm +++ b/ttwhy/lib.cppm @@ -1,5 +1,4 @@ export module ttwhy; -export import ttwhy.io; -export import ttwhy.routers; -export import ttwhy.scanners; +export import ttwhy.core; +export import ttwhy.terminal; diff --git a/ttwhy/routers/concepts.cppm b/ttwhy/routers/concepts.cppm deleted file mode 100644 index cfbcb5a..0000000 --- a/ttwhy/routers/concepts.cppm +++ /dev/null @@ -1,17 +0,0 @@ -module; - -#include <asio.hpp> - -#include <concepts> - -export module ttwhy.routers:concepts; - -namespace ttwhy -{ - - export template<typename Candidate, typename Event> - concept router = requires(Candidate candidate, Event event) { - { candidate.process(event) } -> std::same_as<asio::awaitable<void>>; - }; - -} // namespace ttwhy diff --git a/ttwhy/routers/mod.cppm b/ttwhy/routers/mod.cppm deleted file mode 100644 index d1d2d93..0000000 --- a/ttwhy/routers/mod.cppm +++ /dev/null @@ -1,4 +0,0 @@ -export module ttwhy.routers; - -export import :echo; -export import :concepts; diff --git a/ttwhy/scanners/mod.cppm b/ttwhy/scanners/mod.cppm deleted file mode 100644 index b422a38..0000000 --- a/ttwhy/scanners/mod.cppm +++ /dev/null @@ -1,6 +0,0 @@ -export module ttwhy.scanners; - -export import :concepts; -export import :terminal_events; -export import :terminal_policies; -export import :terminal_scanner; diff --git a/ttwhy/routers/echo.cppm b/ttwhy/terminal/echo.cppm index c9cd7c7..660cf42 100644 --- a/ttwhy/routers/echo.cppm +++ b/ttwhy/terminal/echo.cppm @@ -8,11 +8,12 @@ module; #include <format> #include <string_view> -export module ttwhy.routers:echo; +export module ttwhy.terminal:echo; -import ttwhy.scanners; +import :events; +import ttwhy.core; -namespace ttwhy::routers +namespace ttwhy::terminal { using namespace std::string_view_literals; @@ -43,21 +44,21 @@ namespace ttwhy::routers return m_max_position; } - auto process(scanners::input_event event) -> asio::awaitable<void> + auto process(input_event event) -> asio::awaitable<void> { co_await std::visit( [&](auto && event) -> asio::awaitable<void> { using event_type = std::decay_t<decltype(event)>; - if constexpr (std::same_as<scanners::character_event, event_type>) + if constexpr (std::same_as<character_event, event_type>) { co_await process_character(event.value); } - else if constexpr (std::same_as<scanners::control_event, event_type>) + else if constexpr (std::same_as<control_event, event_type>) { co_await process_control_key(event.key); } - else if constexpr (std::same_as<scanners::navigation_event, event_type>) + else if constexpr (std::same_as<navigation_event, event_type>) { co_await process_navigation_key(event); } @@ -77,11 +78,11 @@ namespace ttwhy::routers } } - auto process_control_key(scanners::control_key key) -> asio::awaitable<void> + auto process_control_key(control_key key) -> asio::awaitable<void> { switch (key) { - case scanners::control_key::backspace: + case control_key::backspace: if (m_cursor_position > 0) { auto [error, bytes_written] = co_await asio::async_write( @@ -96,7 +97,7 @@ namespace ttwhy::routers } } break; - case scanners::control_key::enter: + case control_key::enter: { auto [error, bytes_written] = co_await asio::async_write(m_output_stream, asio::buffer(vte_newline_sequence), asio::as_tuple(asio::use_awaitable)); @@ -107,7 +108,7 @@ namespace ttwhy::routers } break; } - case scanners::control_key::tab: + case control_key::tab: { auto [error, bytes_written] = co_await asio::async_write( m_output_stream, asio::buffer(vte_horizontal_tab_sequence), asio::as_tuple(asio::use_awaitable)); @@ -126,11 +127,11 @@ namespace ttwhy::routers }; } - auto process_navigation_key(scanners::navigation_event event) -> asio::awaitable<void> + auto process_navigation_key(navigation_event event) -> asio::awaitable<void> { switch (event.key) { - case scanners::navigation_key::left: + case navigation_key::left: if (m_cursor_position > 0) { auto [error, bytes_written] = co_await asio::async_write( @@ -142,7 +143,7 @@ namespace ttwhy::routers } break; - case scanners::navigation_key::right: + case navigation_key::right: if (m_cursor_position < m_max_position) { auto [error, bytes_written] = co_await asio::async_write( @@ -154,7 +155,7 @@ namespace ttwhy::routers } break; - case scanners::navigation_key::home: + case navigation_key::home: if (m_cursor_position > 0) { auto sequence = std::format(vte_cursor_left_sequence_format, m_cursor_position); @@ -167,7 +168,7 @@ namespace ttwhy::routers } break; - case scanners::navigation_key::end: + case navigation_key::end: if (m_cursor_position < m_max_position) { auto const distance = m_max_position - m_cursor_position; @@ -181,7 +182,7 @@ namespace ttwhy::routers } break; - case scanners::navigation_key::delete_key: + case navigation_key::delete_key: if (m_cursor_position < m_max_position) { auto [error, bytes_written] = co_await asio::async_write( @@ -203,4 +204,4 @@ namespace ttwhy::routers std::size_t m_max_position{}; }; -} // namespace ttwhy::routers +} // namespace ttwhy::terminal diff --git a/ttwhy/routers/echo.tests.cpp b/ttwhy/terminal/echo.tests.cpp index da2db40..ba07d55 100644 --- a/ttwhy/routers/echo.tests.cpp +++ b/ttwhy/terminal/echo.tests.cpp @@ -6,8 +6,8 @@ #include <string_view> #include <utility> -import ttwhy.routers; -import ttwhy.scanners; +import ttwhy.core; +import ttwhy.terminal; using namespace std::string_view_literals; @@ -52,7 +52,7 @@ namespace struct incomplete_router_wrong_return { - auto process(ttwhy::scanners::input_event) -> void; + auto process(ttwhy::terminal::input_event) -> void; }; struct incomplete_router_wrong_event @@ -63,10 +63,10 @@ namespace TEST_CASE("The router concept validates router candidate interfaces", "[router][concept]") { - 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>); + STATIC_REQUIRE(ttwhy::router<ttwhy::terminal::echo<mock_stream>, ttwhy::terminal::input_event>); + STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_no_process, ttwhy::terminal::input_event>); + STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_wrong_return, ttwhy::terminal::input_event>); + STATIC_REQUIRE_FALSE(ttwhy::router<incomplete_router_wrong_event, ttwhy::terminal::input_event>); } SCENARIO("The echo router handles terminal navigation within the valid printed area", "[router][echo]") @@ -75,7 +75,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a { auto context = asio::io_context{}; auto stream = mock_stream{context.get_executor()}; - auto router = ttwhy::routers::echo{stream}; + auto router = ttwhy::terminal::echo{stream}; auto run_coro = [&](asio::awaitable<void> coro) { asio::co_spawn(context, std::move(coro), asio::detached); @@ -85,8 +85,8 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a WHEN("Typing characters") { - run_coro(router.process(ttwhy::scanners::character_event{'A'})); - run_coro(router.process(ttwhy::scanners::character_event{'B'})); + run_coro(router.process(ttwhy::terminal::character_event{'A'})); + run_coro(router.process(ttwhy::terminal::character_event{'B'})); THEN("Characters are echoed and positions advance") { @@ -98,7 +98,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Navigating left") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::left})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::left})); THEN("The cursor moves left") { @@ -110,7 +110,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Navigating left again to position 0") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::left})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::left})); THEN("The cursor reaches 0") { @@ -122,7 +122,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Attempting to navigate left beyond 0") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::left})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::left})); THEN("Navigation is prevented and nothing is emitted") { @@ -137,7 +137,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Attempting to navigate right beyond what was printed") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::right})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::right})); THEN("Navigation is prevented and nothing is emitted") { @@ -149,9 +149,9 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Navigating left and then overwriting with new character") { - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::left})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::left})); stream.written.clear(); - run_coro(router.process(ttwhy::scanners::character_event{'X'})); + run_coro(router.process(ttwhy::terminal::character_event{'X'})); THEN("The new character is written and max position is preserved") { @@ -164,7 +164,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Using Home and End keys") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::home})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::home})); THEN("Home navigates to 0") { @@ -176,7 +176,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Pressing Home when already at 0") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::home})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::home})); THEN("Nothing is emitted") { @@ -188,7 +188,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Pressing End from 0") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::end})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::end})); THEN("End moves to max position") { @@ -202,7 +202,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Pressing Enter") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::control_event{ttwhy::scanners::control_key::enter})); + run_coro(router.process(ttwhy::terminal::control_event{ttwhy::terminal::control_key::enter})); THEN("Newline is emitted and positions reset") { @@ -214,9 +214,9 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Pressing Backspace at position 0 after reset") { - run_coro(router.process(ttwhy::scanners::control_event{ttwhy::scanners::control_key::enter})); + run_coro(router.process(ttwhy::terminal::control_event{ttwhy::terminal::control_key::enter})); stream.written.clear(); - run_coro(router.process(ttwhy::scanners::control_event{ttwhy::scanners::control_key::backspace})); + run_coro(router.process(ttwhy::terminal::control_event{ttwhy::terminal::control_key::backspace})); THEN("Backspace does nothing at position 0") { @@ -228,9 +228,9 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Using Delete key") { - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::left})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::left})); stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::delete_key})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::delete_key})); THEN("Delete character sequence is emitted and max position shrinks") { @@ -242,7 +242,7 @@ SCENARIO("The echo router handles terminal navigation within the valid printed a AND_WHEN("Pressing Delete when cursor is at max position") { stream.written.clear(); - run_coro(router.process(ttwhy::scanners::navigation_event{ttwhy::scanners::navigation_key::delete_key})); + run_coro(router.process(ttwhy::terminal::navigation_event{ttwhy::terminal::navigation_key::delete_key})); THEN("Nothing is emitted") { diff --git a/ttwhy/scanners/terminal_events.cppm b/ttwhy/terminal/events.cppm index 3e4c849..93b2326 100644 --- a/ttwhy/scanners/terminal_events.cppm +++ b/ttwhy/terminal/events.cppm @@ -4,9 +4,11 @@ module; #include <utility> #include <variant> -export module ttwhy.scanners:terminal_events; +export module ttwhy.terminal:events; -export namespace ttwhy::scanners +import ttwhy.core; + +export namespace ttwhy::terminal { enum struct control_key : std::uint8_t { @@ -97,4 +99,9 @@ export namespace ttwhy::scanners }; using input_event = std::variant<character_event, control_event, navigation_event, ctrl_chord_event>; -} // namespace ttwhy::scanners + + template<typename Sink> + concept event_sink = ttwhy::event_sink<Sink, character_event> && ttwhy::event_sink<Sink, control_event> && + ttwhy::event_sink<Sink, navigation_event>; + +} // namespace ttwhy::terminal diff --git a/ttwhy/terminal/mod.cppm b/ttwhy/terminal/mod.cppm new file mode 100644 index 0000000..2608c14 --- /dev/null +++ b/ttwhy/terminal/mod.cppm @@ -0,0 +1,9 @@ +export module ttwhy.terminal; + +export import :echo; +export import :events; +export import :policies; +export import :readers; +export import :scanner; +export import :scoped_attributes; +export import :signal_handling; diff --git a/ttwhy/scanners/terminal_policies.cppm b/ttwhy/terminal/policies.cppm index e3c889c..acf9371 100644 --- a/ttwhy/scanners/terminal_policies.cppm +++ b/ttwhy/terminal/policies.cppm @@ -3,12 +3,11 @@ module; #include <optional> #include <string> -export module ttwhy.scanners:terminal_policies; +export module ttwhy.terminal:policies; -import :concepts; -import :terminal_events; +import :events; -namespace ttwhy::scanners +namespace ttwhy::terminal { namespace detail @@ -61,7 +60,7 @@ namespace ttwhy::scanners export struct ansi_policy { - constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::terminal_event_sink auto & sink) -> void + constexpr auto static resolve_vt220_keypad(std::string & buffer, event_sink auto & sink) -> void { if (buffer.empty()) { @@ -75,8 +74,7 @@ namespace ttwhy::scanners buffer.clear(); } - constexpr auto static resolve_vt100_cursor(char terminator, std::string &, ttwhy::terminal_event_sink auto & sink) - -> void + constexpr auto static resolve_vt100_cursor(char terminator, std::string &, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { @@ -84,7 +82,7 @@ namespace ttwhy::scanners } } - constexpr auto static resolve_ss3(char terminator, ttwhy::terminal_event_sink auto & sink) -> void + constexpr auto static resolve_ss3(char terminator, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { @@ -122,7 +120,7 @@ namespace ttwhy::scanners return static_cast<modifier_set>(modifier_value - 1); } - constexpr auto static resolve_vt220_keypad(std::string & buffer, ttwhy::terminal_event_sink auto & sink) -> void + constexpr auto static resolve_vt220_keypad(std::string & buffer, event_sink auto & sink) -> void { if (buffer.empty()) { @@ -138,8 +136,7 @@ namespace ttwhy::scanners buffer.clear(); } - constexpr auto static resolve_vt100_cursor(char terminator, std::string & buffer, - ttwhy::terminal_event_sink auto & sink) -> void + constexpr auto static resolve_vt100_cursor(char terminator, std::string & buffer, event_sink auto & sink) -> void { auto modifiers = parse_modifiers(buffer); @@ -149,7 +146,7 @@ namespace ttwhy::scanners } } - constexpr auto static resolve_ss3(char terminator, ttwhy::terminal_event_sink auto & sink) -> void + constexpr auto static resolve_ss3(char terminator, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { @@ -158,4 +155,4 @@ namespace ttwhy::scanners } }; -} // namespace ttwhy::scanners +} // namespace ttwhy::terminal diff --git a/ttwhy/io/readers.cppm b/ttwhy/terminal/readers.cppm index 56ce2b0..ffa5687 100644 --- a/ttwhy/io/readers.cppm +++ b/ttwhy/terminal/readers.cppm @@ -8,16 +8,17 @@ module; #include <span> #include <vector> -export module ttwhy.io:readers; +export module ttwhy.terminal:readers; -import ttwhy.routers; -import ttwhy.scanners; +import :events; +import :policies; +import :scanner; +import ttwhy.core; -namespace ttwhy::io +namespace ttwhy::terminal { - export template<typename TerminalPolicy = scanners::xterm_policy, typename InputStream, - router<scanners::input_event> AppRouter> + export template<typename TerminalPolicy = xterm_policy, typename InputStream, ttwhy::router<input_event> AppRouter> auto read_events(InputStream & stream, AppRouter & router) -> asio::awaitable<void> { using namespace asio::experimental::awaitable_operators; @@ -26,14 +27,14 @@ namespace ttwhy::io auto executor = co_await asio::this_coro::executor; auto timer = asio::steady_timer{executor}; - auto queue = std::vector<scanners::input_event>{}; + auto queue = std::vector<input_event>{}; queue.reserve(16); auto sink = [&queue](auto const & event) { queue.push_back(event); }; - auto scanner = scanners::terminal_scanner<decltype(sink), TerminalPolicy>{sink}; + auto scanner = terminal::scanner<decltype(sink), TerminalPolicy>{sink}; auto raw_buffer = std::array<char, 64>{}; @@ -90,4 +91,4 @@ namespace ttwhy::io } } -} // namespace ttwhy::io +} // namespace ttwhy::terminal diff --git a/ttwhy/scanners/terminal_scanner.cppm b/ttwhy/terminal/scanner.cppm index a791909..8a722b4 100644 --- a/ttwhy/scanners/terminal_scanner.cppm +++ b/ttwhy/terminal/scanner.cppm @@ -7,13 +7,13 @@ module; #include <span> #include <string> -export module ttwhy.scanners:terminal_scanner; +export module ttwhy.terminal:scanner; -import :concepts; -import :terminal_events; -import :terminal_policies; +import :events; +import :policies; +import ttwhy.core; -namespace ttwhy::scanners::detail +namespace ttwhy::terminal::detail { /// Events @@ -95,7 +95,7 @@ namespace ttwhy::scanners::detail /// Transitions - template<terminal_event_sink Sink, typename TerminalPolicy> + template<event_sink Sink, typename TerminalPolicy> struct transition_table { auto operator()() const noexcept @@ -195,15 +195,15 @@ namespace ttwhy::scanners::detail } }; -} // namespace ttwhy::scanners::detail +} // namespace ttwhy::terminal::detail -export namespace ttwhy::scanners +export namespace ttwhy::terminal { - template<terminal_event_sink Sink, typename TerminalPolicy> - struct terminal_scanner + template<event_sink Sink, typename TerminalPolicy> + struct scanner { - explicit terminal_scanner(Sink & sink) + explicit scanner(Sink & sink) : m_state_machine{sink, m_csi_buffer} {} @@ -230,7 +230,7 @@ export namespace ttwhy::scanners m_state_machine; }; - template<terminal_event_sink Sink> - using ansi = terminal_scanner<Sink, ansi_policy>; + template<event_sink Sink> + using ansi = scanner<Sink, ansi_policy>; -} // namespace ttwhy::scanners +} // namespace ttwhy::terminal diff --git a/ttwhy/scanners/terminal_scanner.tests.cpp b/ttwhy/terminal/scanner.tests.cpp index f4ea6ad..64acb2d 100644 --- a/ttwhy/scanners/terminal_scanner.tests.cpp +++ b/ttwhy/terminal/scanner.tests.cpp @@ -4,20 +4,21 @@ #include <variant> #include <vector> -import ttwhy.scanners; +import ttwhy.core; +import ttwhy.terminal; using namespace std::string_view_literals; -[[nodiscard]] constexpr auto static is_character(ttwhy::scanners::input_event & event, char expected) -> bool +[[nodiscard]] constexpr auto static is_character(ttwhy::terminal::input_event & event, char expected) -> bool { - auto const * data = std::get_if<ttwhy::scanners::character_event>(&event); + auto const * data = std::get_if<ttwhy::terminal::character_event>(&event); return data != nullptr && data->value == expected; } -[[nodiscard]] constexpr auto static is_control(ttwhy::scanners::input_event & event, - ttwhy::scanners::control_key expected) -> bool +[[nodiscard]] constexpr auto static is_control(ttwhy::terminal::input_event & event, + ttwhy::terminal::control_key expected) -> bool { - auto const * data = std::get_if<ttwhy::scanners::control_event>(&event); + auto const * data = std::get_if<ttwhy::terminal::control_event>(&event); return data != nullptr && data->key == expected; } @@ -25,11 +26,11 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha { GIVEN("An initialized scanner and event sink") { - auto queue = std::vector<ttwhy::scanners::input_event>{}; + auto queue = std::vector<ttwhy::terminal::input_event>{}; auto sink = [&queue](auto const & event) { queue.push_back(event); }; - auto scanner = ttwhy::scanners::ansi{sink}; + auto scanner = ttwhy::terminal::ansi{sink}; WHEN("Processing a standard printable character") { @@ -49,7 +50,7 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha THEN("It yields a backspace control event") { REQUIRE(queue.size() == 1); - CHECK(is_control(queue.at(0), ttwhy::scanners::control_key::backspace)); + CHECK(is_control(queue.at(0), ttwhy::terminal::control_key::backspace)); } } @@ -60,7 +61,7 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha THEN("It yields a backspace control event") { REQUIRE(queue.size() == 1); - CHECK(is_control(queue.at(0), ttwhy::scanners::control_key::backspace)); + CHECK(is_control(queue.at(0), ttwhy::terminal::control_key::backspace)); } } @@ -71,7 +72,7 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha THEN("It yields a tab control event") { REQUIRE(queue.size() == 1); - CHECK(is_control(queue.at(0), ttwhy::scanners::control_key::tab)); + CHECK(is_control(queue.at(0), ttwhy::terminal::control_key::tab)); } } @@ -82,7 +83,7 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha THEN("It yields an enter control event") { REQUIRE(queue.size() == 1); - CHECK(is_control(queue.at(0), ttwhy::scanners::control_key::enter)); + CHECK(is_control(queue.at(0), ttwhy::terminal::control_key::enter)); } } @@ -93,7 +94,7 @@ SCENARIO("The ANSI scanner processes printable ASCII and standard C0 control cha THEN("It yields an enter control event") { REQUIRE(queue.size() == 1); - CHECK(is_control(queue.at(0), ttwhy::scanners::control_key::enter)); + CHECK(is_control(queue.at(0), ttwhy::terminal::control_key::enter)); } } } diff --git a/ttwhy/io/scoped_attributes.cppm b/ttwhy/terminal/scoped_attributes.cppm index 5e42e39..2ca34a3 100644 --- a/ttwhy/io/scoped_attributes.cppm +++ b/ttwhy/terminal/scoped_attributes.cppm @@ -7,9 +7,9 @@ module; #include <system_error> #include <utility> -export module ttwhy.io:scoped_attributes; +export module ttwhy.terminal:scoped_attributes; -namespace ttwhy::io +namespace ttwhy::terminal { auto static read_attributes(int file_descriptor) -> termios @@ -132,4 +132,4 @@ namespace ttwhy::io termios m_attributes; }; -} // namespace ttwhy::io +} // namespace ttwhy::terminal diff --git a/ttwhy/io/signal_handling.cppm b/ttwhy/terminal/signal_handling.cppm index 1f3fecc..a3b5d4d 100644 --- a/ttwhy/io/signal_handling.cppm +++ b/ttwhy/terminal/signal_handling.cppm @@ -6,9 +6,9 @@ module; #include <format> #include <system_error> -export module ttwhy.io:signal_handling; +export module ttwhy.terminal:signal_handling; -namespace ttwhy::io +namespace ttwhy::terminal { export template<typename Stream, typename TerminalAttributes> @@ -55,4 +55,4 @@ namespace ttwhy::io } } -} // namespace ttwhy::io +} // namespace ttwhy::terminal |
