input: Kitty encodes alternate keys

This commit is contained in:
Mitchell Hashimoto
2023-08-17 09:48:15 -07:00
parent fe0e1f5ee8
commit 6493da0dd3
2 changed files with 67 additions and 4 deletions

View File

@ -51,10 +51,22 @@ fn kitty(
// Find the entry for this key in the kitty table.
const entry_: ?KittyEntry = entry: {
// Functional or predefined keys
for (kitty_entries) |entry| {
if (entry.key == self.event.key) break :entry entry;
}
// Otherwise, we use our unicode codepoint from UTF8. We
// always use the unshifted value.
if (self.event.unshifted_codepoint > 0) {
break :entry .{
.key = self.event.key,
.code = self.event.unshifted_codepoint,
.final = 'u',
.modifier = false,
};
}
break :entry null;
};
@ -119,6 +131,16 @@ fn kitty(
};
}
if (self.kitty_flags.report_alternates) alternates: {
const view = try std.unicode.Utf8View.init(self.event.utf8);
var it = view.iterator();
const cp = it.nextCodepoint() orelse break :alternates;
if (it.nextCodepoint() != null) break :alternates;
if (cp != seq.key) {
seq.alternates = &.{cp};
}
}
if (self.kitty_flags.report_associated) {
seq.text = self.event.utf8;
}
@ -521,11 +543,11 @@ const KittyMods = packed struct(u8) {
///
/// CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
const KittySequence = struct {
key: u16,
key: u21,
final: u8,
mods: KittyMods = .{},
event: Event = .none,
alternates: []const u16 = &.{},
alternates: []const u21 = &.{},
text: []const u8 = "",
/// Values for the event code (see "event-type" in above comment).
@ -777,6 +799,47 @@ test "kitty: composing with modifier" {
try testing.expectEqualStrings("\x1b[57441;2u", actual);
}
test "kitty: shift+a on US keyboard" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.mods = .{ .shift = true },
.utf8 = "A",
.unshifted_codepoint = 97, // lowercase A
},
.kitty_flags = .{
.disambiguate = true,
.report_alternates = true,
},
};
const actual = try enc.kitty(&buf);
try testing.expectEqualStrings("\x1b[97:65;2u", actual);
}
test "kitty: matching unshifted codepoint" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.mods = .{ .shift = true },
.utf8 = "A",
.unshifted_codepoint = 65,
},
.kitty_flags = .{
.disambiguate = true,
.report_alternates = true,
},
};
// WARNING: This is not a valid encoding. This is a hypothetical encoding
// just to test that our logic is correct around matching unshifted
// codepoints.
const actual = try enc.kitty(&buf);
try testing.expectEqualStrings("\x1b[65;2u", actual);
}
test "legacy: ctrl+alt+c" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{

View File

@ -6,7 +6,7 @@ const key = @import("key.zig");
/// for a given key.
pub const Entry = struct {
key: key.Key,
code: u16,
code: u21,
final: u8,
modifier: bool,
};
@ -28,7 +28,7 @@ pub const entries: []const Entry = entries: {
/// Raw entry is the tuple form of an entry for easy human management.
/// This should never be used in a real program so it is not pub. For
/// real programs, use `entries` which has properly typed, structured data.
const RawEntry = struct { key.Key, u16, u8, bool };
const RawEntry = struct { key.Key, u21, u8, bool };
/// The raw data for how to map keys to Kitty data. Based on the information:
/// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#functional-key-definitions