module; #include #include #include export module ttwhy.routers:echo; import ttwhy; import ttwhy.scanners; namespace ttwhy::routers { using namespace std::string_view_literals; constexpr auto vte_backspace_sequence = "\b \b"sv; constexpr auto vte_newline_sequence = "\r\n"sv; constexpr auto vte_horizontal_tab_sequqnce = "\t"sv; export template struct echo { using terminal_policy = scanners::xterm_policy; explicit echo(StreamType & stream) : m_output_stream{stream} {} auto process(scanners::input_event event) -> asio::awaitable { co_await std::visit( [&](auto && event) -> asio::awaitable { using event_type = std::decay_t; if constexpr (std::same_as) { co_await process_character(event.value); } else if constexpr (std::same_as) { co_await process_control_key(event.key); } else if constexpr (std::same_as) { co_await process_navigation_key(event); } }, event); } private: auto process_character(char character) -> asio::awaitable { co_await asio::async_write(m_output_stream, asio::buffer(&character, 1), asio::as_tuple(asio::use_awaitable)); } auto process_control_key(scanners::control_key key) -> asio::awaitable { switch (key) { case scanners::control_key::backspace: co_await asio::async_write(m_output_stream, asio::buffer(vte_backspace_sequence), asio::as_tuple(asio::use_awaitable)); break; case scanners::control_key::enter: co_await asio::async_write(m_output_stream, asio::buffer(vte_newline_sequence), asio::as_tuple(asio::use_awaitable)); break; case scanners::control_key::tab: co_await asio::async_write(m_output_stream, asio::buffer(vte_horizontal_tab_sequqnce), asio::as_tuple(asio::use_awaitable)); break; default: co_await asio::async_write(m_output_stream, asio::buffer(std::format("{{CTRL:{}}}", std::to_underlying(key))), asio::as_tuple(asio::use_awaitable)); break; }; } auto process_navigation_key(scanners::navigation_event event) -> asio::awaitable { auto modifiers = std::to_underlying(event.modifiers); switch (event.key) { case scanners::navigation_key::delete_key: { auto message = std::format("{{DEL, MODS:{}}}", static_cast(modifiers)); co_await asio::async_write(m_output_stream, asio::buffer(message), asio::as_tuple(asio::use_awaitable)); break; } default: { auto message = std::format("{{NAV:{}, MODS:{}}}", static_cast(event.key), static_cast(modifiers)); co_await asio::async_write(m_output_stream, asio::buffer(message), asio::as_tuple(asio::use_awaitable)); } } } StreamType & m_output_stream; }; } // namespace ttwhy::routers