module; #include #include export module ttwhy.terminal:policies; import :events; namespace ttwhy::terminal { namespace detail { constexpr auto map_vt220_keypad(char terminator) -> std::optional { switch (terminator) { case '1': case '7': return navigation_key::home; case '2': return navigation_key::insert_key; case '3': return navigation_key::delete_key; case '4': case '8': return navigation_key::end; case '5': return navigation_key::page_up; case '6': return navigation_key::page_down; default: return std::nullopt; } } constexpr auto map_vt100_cursor(char terminator) -> std::optional { switch (terminator) { case 'A': return navigation_key::up; case 'B': return navigation_key::down; case 'C': return navigation_key::right; case 'D': return navigation_key::left; case 'H': return navigation_key::home; case 'F': return navigation_key::end; default: return std::nullopt; } } } // namespace detail export struct ansi_policy { constexpr auto static resolve_vt220_keypad(std::string & buffer, event_sink auto & sink) -> void { if (buffer.empty()) { return; } if (auto key = detail::map_vt220_keypad(buffer.front())) { sink(navigation_event{*key}); } buffer.clear(); } constexpr auto static resolve_vt100_cursor(char terminator, std::string &, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { sink(navigation_event{*key}); } } constexpr auto static resolve_ss3(char terminator, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { sink(navigation_event{*key}); } } }; export struct xterm_policy { constexpr auto static parse_modifiers(std::string_view buffer) -> modifier_set { auto delimiter = buffer.find(';'); if (delimiter == std::string_view::npos) { return {}; } auto modifier_string = buffer.substr(delimiter + 1); auto modifier_value = 0u; for (auto character : modifier_string) { if (character >= '0' && character <= '9') { modifier_value = modifier_value * 10 + static_cast(character - '0'); } } if (modifier_value <= 1) { return {}; } return static_cast(modifier_value - 1); } constexpr auto static resolve_vt220_keypad(std::string & buffer, event_sink auto & sink) -> void { if (buffer.empty()) { return; } auto modifiers = parse_modifiers(buffer); if (auto key = detail::map_vt220_keypad(buffer.front())) { sink(navigation_event{*key, modifiers}); } buffer.clear(); } constexpr auto static resolve_vt100_cursor(char terminator, std::string & buffer, event_sink auto & sink) -> void { auto modifiers = parse_modifiers(buffer); if (auto key = detail::map_vt100_cursor(terminator)) { sink(navigation_event{*key, modifiers}); } } constexpr auto static resolve_ss3(char terminator, event_sink auto & sink) -> void { if (auto key = detail::map_vt100_cursor(terminator)) { sink(navigation_event{*key}); } } }; } // namespace ttwhy::terminal