1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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'));
}
|