aboutsummaryrefslogtreecommitdiff
path: root/ttwhy/terminal/policies.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'ttwhy/terminal/policies.cppm')
-rw-r--r--ttwhy/terminal/policies.cppm158
1 files changed, 158 insertions, 0 deletions
diff --git a/ttwhy/terminal/policies.cppm b/ttwhy/terminal/policies.cppm
new file mode 100644
index 0000000..acf9371
--- /dev/null
+++ b/ttwhy/terminal/policies.cppm
@@ -0,0 +1,158 @@
+module;
+
+#include <optional>
+#include <string>
+
+export module ttwhy.terminal:policies;
+
+import :events;
+
+namespace ttwhy::terminal
+{
+
+ namespace detail
+ {
+ constexpr auto map_vt220_keypad(char terminator) -> std::optional<navigation_key>
+ {
+ 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<navigation_key>
+ {
+ 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<unsigned int>(character - '0');
+ }
+ }
+
+ if (modifier_value <= 1)
+ {
+ return {};
+ }
+
+ return static_cast<modifier_set>(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