aboutsummaryrefslogtreecommitdiff
path: root/ttwhy
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-06-19 19:47:03 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-06-19 19:47:40 +0200
commit90fa52db708c42d9707581156b957da99987bd1c (patch)
tree5afd9b4daf9254cd969b9d3f8082af46bedb19a5 /ttwhy
parent7da39cd68d2bed2f49452ac5f9a3c01c52d0c5ba (diff)
downloadttwhy-90fa52db708c42d9707581156b957da99987bd1c.tar.xz
ttwhy-90fa52db708c42d9707581156b957da99987bd1c.zip
lib/scanners: inject scanner sink
Diffstat (limited to 'ttwhy')
-rw-r--r--ttwhy/io.cppm10
-rw-r--r--ttwhy/scanners/ansi.cppm247
2 files changed, 130 insertions, 127 deletions
diff --git a/ttwhy/io.cppm b/ttwhy/io.cppm
index 5fd5e50..4b83996 100644
--- a/ttwhy/io.cppm
+++ b/ttwhy/io.cppm
@@ -3,7 +3,7 @@ module;
#include <asio.hpp>
#include <asio/experimental/awaitable_operators.hpp>
-#include <chrono>
+#include <chrono> // IWYU pragma: keep
#include <format>
#include <span>
#include <vector>
@@ -71,7 +71,11 @@ namespace ttwhy::io
auto queue = std::vector<scanners::input_event>{};
queue.reserve(16);
- auto scanner = scanners::ansi{queue};
+ auto sink = [&queue](auto const & event) {
+ queue.push_back(event);
+ };
+ auto scanner = scanners::ansi{sink};
+
auto raw_buffer = std::array<char, 64>{};
while (true)
@@ -81,7 +85,7 @@ namespace ttwhy::io
if (scanner.is_pending())
{
- timer.expires_after(500ms);
+ timer.expires_after(50ms);
auto result = co_await (stream.async_read_some(asio::buffer(raw_buffer), asio::as_tuple(asio::use_awaitable)) ||
timer.async_wait(asio::as_tuple(asio::use_awaitable)));
diff --git a/ttwhy/scanners/ansi.cppm b/ttwhy/scanners/ansi.cppm
index b248753..886e699 100644
--- a/ttwhy/scanners/ansi.cppm
+++ b/ttwhy/scanners/ansi.cppm
@@ -5,7 +5,6 @@ module;
#include <span>
#include <string>
-#include <vector>
export module ttwhy.scanners:ansi;
@@ -32,126 +31,6 @@ namespace ttwhy::scanners::detail
constexpr auto csi_sequence = boost::sml::state<class csi_sequence>;
constexpr auto ss3_sequence = boost::sml::state<class ss3_sequence>;
- /// Actions
-
- constexpr auto push_character = [](byte_received const & event, std::vector<input_event> & queue) {
- queue.push_back(character_event{event.value});
- };
-
- constexpr auto push_backspace = [](std::vector<input_event> & queue) {
- queue.push_back(control_event{control_key::backspace});
- };
-
- constexpr auto push_tab = [](std::vector<input_event> & queue) {
- queue.push_back(control_event(control_key::tab));
- };
-
- constexpr auto push_enter = [](std::vector<input_event> & queue) {
- queue.push_back(control_event(control_key::enter));
- };
-
- constexpr auto emit_timeout_escape = [](std::vector<input_event> & queue, std::string & buffer) {
- queue.push_back(control_event{control_key::escape});
- buffer.clear();
- };
-
- constexpr auto fallback_escape = [](byte_received const & event, std::vector<input_event> & queue) {
- queue.push_back(control_event{control_key::escape});
- if (event.value >= 0x20 && event.value <= 0x7e)
- {
- queue.push_back(character_event{event.value});
- }
- };
-
- constexpr auto clear_csi = [](std::string & buffer) {
- buffer.clear();
- };
-
- constexpr auto push_csi_parameter = [](byte_received const & event, std::string & buffer) {
- buffer.push_back(event.value);
- };
-
- constexpr auto resolve_csi = [](byte_received const & event, std::string & buffer, std::vector<input_event> & queue) {
- if (event.value == '~')
- {
- switch (buffer.at(0))
- {
- case '1':
- case '7':
- queue.push_back(navigation_event{navigation_key::home});
- break;
- case '2':
- queue.push_back(navigation_event{navigation_key::insert_key});
- break;
- case '3':
- queue.push_back(navigation_event{navigation_key::delete_key});
- break;
- case '4':
- case '8':
- queue.push_back(navigation_event{navigation_key::end});
- break;
- case '5':
- queue.push_back(navigation_event{navigation_key::page_up});
- break;
- case '6':
- queue.push_back(navigation_event{navigation_key::page_down});
- break;
- default:
- }
- }
- else
- {
- switch (event.value)
- {
- case 'A':
- queue.push_back(navigation_event{navigation_key::up});
- break;
- case 'B':
- queue.push_back(navigation_event{navigation_key::down});
- break;
- case 'C':
- queue.push_back(navigation_event{navigation_key::right});
- break;
- case 'D':
- queue.push_back(navigation_event{navigation_key::left});
- break;
- case 'H':
- queue.push_back(navigation_event{navigation_key::home});
- break;
- case 'F':
- queue.push_back(navigation_event{navigation_key::end});
- break;
- default:
- }
- }
- buffer.clear();
- };
-
- constexpr auto resolve_ss3 = [](byte_received const & event, std::vector<input_event> & queue) {
- switch (event.value)
- {
- case 'A':
- queue.push_back(navigation_event{navigation_key::up});
- break;
- case 'B':
- queue.push_back(navigation_event{navigation_key::down});
- break;
- case 'C':
- queue.push_back(navigation_event{navigation_key::right});
- break;
- case 'D':
- queue.push_back(navigation_event{navigation_key::left});
- break;
- case 'H':
- queue.push_back(navigation_event{navigation_key::home});
- break;
- case 'F':
- queue.push_back(navigation_event{navigation_key::end});
- break;
- default:
- }
- };
-
/// Guards
constexpr auto is_backspace = [](byte_received e) {
@@ -196,12 +75,131 @@ namespace ttwhy::scanners::detail
/// Transitions
+ template<typename SinkType>
struct transition_table
{
auto operator()() const noexcept
{
using namespace boost::sml;
+ constexpr auto push_character = [](byte_received const & event, SinkType & sink) {
+ sink(character_event{event.value});
+ };
+
+ constexpr auto push_backspace = [](SinkType & sink) {
+ sink(control_event{control_key::backspace});
+ };
+
+ constexpr auto push_tab = [](SinkType & sink) {
+ sink(control_event(control_key::tab));
+ };
+
+ constexpr auto push_enter = [](SinkType & sink) {
+ sink(control_event(control_key::enter));
+ };
+
+ constexpr auto emit_timeout_escape = [](SinkType & sink, std::string & buffer) {
+ sink(control_event{control_key::escape});
+ buffer.clear();
+ };
+
+ constexpr auto fallback_escape = [](byte_received const & event, SinkType & sink) {
+ sink(control_event{control_key::escape});
+ if (event.value >= 0x20 && event.value <= 0x7e)
+ {
+ sink(character_event{event.value});
+ }
+ };
+
+ constexpr auto clear_csi = [](std::string & buffer) {
+ buffer.clear();
+ };
+
+ constexpr auto push_csi_parameter = [](byte_received const & event, std::string & buffer) {
+ buffer.push_back(event.value);
+ };
+
+ constexpr auto resolve_csi = [](byte_received const & event, std::string & buffer, SinkType & sink) {
+ if (event.value == '~')
+ {
+ switch (buffer.at(0))
+ {
+ case '1':
+ case '7':
+ sink(navigation_event{navigation_key::home});
+ break;
+ case '2':
+ sink(navigation_event{navigation_key::insert_key});
+ break;
+ case '3':
+ sink(navigation_event{navigation_key::delete_key});
+ break;
+ case '4':
+ case '8':
+ sink(navigation_event{navigation_key::end});
+ break;
+ case '5':
+ sink(navigation_event{navigation_key::page_up});
+ break;
+ case '6':
+ sink(navigation_event{navigation_key::page_down});
+ break;
+ default:
+ }
+ }
+ else
+ {
+ switch (event.value)
+ {
+ case 'A':
+ sink(navigation_event{navigation_key::up});
+ break;
+ case 'B':
+ sink(navigation_event{navigation_key::down});
+ break;
+ case 'C':
+ sink(navigation_event{navigation_key::right});
+ break;
+ case 'D':
+ sink(navigation_event{navigation_key::left});
+ break;
+ case 'H':
+ sink(navigation_event{navigation_key::home});
+ break;
+ case 'F':
+ sink(navigation_event{navigation_key::end});
+ break;
+ default:
+ }
+ }
+ buffer.clear();
+ };
+
+ constexpr auto resolve_ss3 = [](byte_received const & event, SinkType & sink) {
+ switch (event.value)
+ {
+ case 'A':
+ sink(navigation_event{navigation_key::up});
+ break;
+ case 'B':
+ sink(navigation_event{navigation_key::down});
+ break;
+ case 'C':
+ sink(navigation_event{navigation_key::right});
+ break;
+ case 'D':
+ sink(navigation_event{navigation_key::left});
+ break;
+ case 'H':
+ sink(navigation_event{navigation_key::home});
+ break;
+ case 'F':
+ sink(navigation_event{navigation_key::end});
+ break;
+ default:
+ }
+ };
+
// clang-format off
return make_transition_table(
*idle + event<byte_received>[is_escape] = escape_sequence,
@@ -231,10 +229,11 @@ namespace ttwhy::scanners::detail
export namespace ttwhy::scanners
{
+ template<typename SinkType>
struct ansi
{
- explicit ansi(std::vector<input_event> & queue)
- : m_state_machine{queue, m_csi_buffer}
+ explicit ansi(SinkType & sink)
+ : m_state_machine{sink, m_csi_buffer}
{}
auto process(std::span<char const> buffer) -> void
@@ -256,7 +255,7 @@ export namespace ttwhy::scanners
private:
std::string m_csi_buffer{};
- boost::sml::sm<detail::transition_table> m_state_machine;
+ boost::sml::sm<detail::transition_table<SinkType>> m_state_machine;
};
} // namespace ttwhy::scanners