//! 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')); }