summaryrefslogtreecommitdiff
path: root/src/vaxis_input.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/vaxis_input.zig')
-rw-r--r--src/vaxis_input.zig77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/vaxis_input.zig b/src/vaxis_input.zig
new file mode 100644
index 00000000..0e25dea1
--- /dev/null
+++ b/src/vaxis_input.zig
@@ -0,0 +1,77 @@
+//! A key as vaxis parses it from a terminal's bytes, as the core's Event:
+//! the one map for every shell that reads a terminal (tty, gui's stdin,
+//! esp32p4). Three copies had drifted; the gui's had lost the F-keys,
+//! Insert and the keypad.
+const std = @import("std");
+const vaxis = @import("vaxis");
+const pardes = @import("pardes.zig");
+
+/// The effective codepoint the way vaxis's own `Key.matches` sees it: a
+/// single-character `text` wins, the terminal having resolved shift;
+/// otherwise the shifted codepoint.
+pub fn effCp(key: vaxis.Key) u21 {
+ if (key.text) |t| {
+ const view = std.unicode.Utf8View.init(t) catch return key.codepoint;
+ var it = view.iterator();
+ if (it.nextCodepoint()) |c| {
+ if (it.nextCodepoint() == null) return c;
+ }
+ }
+ return key.shifted_codepoint orelse key.codepoint;
+}
+
+/// vaxis's functional-key codepoints as the core's; the ASCII ones
+/// (enter, tab, escape, backspace) already coincide.
+pub fn mapKey(cp: u21) u21 {
+ return switch (cp) {
+ vaxis.Key.kp_enter => pardes.Key.enter,
+ vaxis.Key.up => pardes.Key.up,
+ vaxis.Key.down => pardes.Key.down,
+ vaxis.Key.left => pardes.Key.left,
+ vaxis.Key.right => pardes.Key.right,
+ vaxis.Key.home => pardes.Key.home,
+ vaxis.Key.end => pardes.Key.end,
+ vaxis.Key.page_up => pardes.Key.page_up,
+ vaxis.Key.page_down => pardes.Key.page_down,
+ vaxis.Key.delete => pardes.Key.delete,
+ vaxis.Key.insert => pardes.Key.insert,
+ vaxis.Key.print_screen => pardes.Key.print_screen,
+ vaxis.Key.scroll_lock => pardes.Key.scroll_lock,
+ vaxis.Key.pause => pardes.Key.pause,
+ vaxis.Key.menu => pardes.Key.menu,
+ vaxis.Key.f1...vaxis.Key.f25 => pardes.Key.f1 + (cp - vaxis.Key.f1),
+ // The keypad's own keys, which the kitty keyboard protocol tells
+ // apart, do what the keys they are named for do.
+ vaxis.Key.kp_left => pardes.Key.left,
+ vaxis.Key.kp_right => pardes.Key.right,
+ vaxis.Key.kp_up => pardes.Key.up,
+ vaxis.Key.kp_down => pardes.Key.down,
+ vaxis.Key.kp_page_up => pardes.Key.page_up,
+ vaxis.Key.kp_page_down => pardes.Key.page_down,
+ vaxis.Key.kp_home => pardes.Key.home,
+ vaxis.Key.kp_end => pardes.Key.end,
+ vaxis.Key.kp_insert => pardes.Key.insert,
+ vaxis.Key.kp_delete => pardes.Key.delete,
+ else => cp,
+ };
+}
+
+/// The key as the core's event, its text the key's own.
+pub fn keyEvent(key: vaxis.Key) pardes.Event {
+ return .{ .key = .{
+ .cp = mapKey(effCp(key)),
+ .text = key.text orelse "",
+ .ctrl = key.mods.ctrl,
+ .alt = key.mods.alt,
+ .shift = key.mods.shift,
+ } };
+}
+
+test "F-keys, Insert and the keypad map to the core's keys" {
+ try std.testing.expectEqual(pardes.Key.f1 + 4, mapKey(vaxis.Key.f5));
+ try std.testing.expectEqual(pardes.Key.f1 + 24, mapKey(vaxis.Key.f25));
+ try std.testing.expectEqual(pardes.Key.insert, mapKey(vaxis.Key.insert));
+ try std.testing.expectEqual(pardes.Key.up, mapKey(vaxis.Key.kp_up));
+ try std.testing.expectEqual(pardes.Key.enter, keyEvent(.{ .codepoint = vaxis.Key.kp_enter }).key.cp);
+ try std.testing.expectEqual(@as(u21, 'a'), mapKey('a'));
+}