mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
input: Kitty encodes alternate keys
This commit is contained in:
@ -51,10 +51,22 @@ fn kitty(
|
|||||||
|
|
||||||
// Find the entry for this key in the kitty table.
|
// Find the entry for this key in the kitty table.
|
||||||
const entry_: ?KittyEntry = entry: {
|
const entry_: ?KittyEntry = entry: {
|
||||||
|
// Functional or predefined keys
|
||||||
for (kitty_entries) |entry| {
|
for (kitty_entries) |entry| {
|
||||||
if (entry.key == self.event.key) break :entry 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;
|
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) {
|
if (self.kitty_flags.report_associated) {
|
||||||
seq.text = self.event.utf8;
|
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
|
/// CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
|
||||||
const KittySequence = struct {
|
const KittySequence = struct {
|
||||||
key: u16,
|
key: u21,
|
||||||
final: u8,
|
final: u8,
|
||||||
mods: KittyMods = .{},
|
mods: KittyMods = .{},
|
||||||
event: Event = .none,
|
event: Event = .none,
|
||||||
alternates: []const u16 = &.{},
|
alternates: []const u21 = &.{},
|
||||||
text: []const u8 = "",
|
text: []const u8 = "",
|
||||||
|
|
||||||
/// Values for the event code (see "event-type" in above comment).
|
/// 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);
|
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" {
|
test "legacy: ctrl+alt+c" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var enc: KeyEncoder = .{
|
var enc: KeyEncoder = .{
|
||||||
|
@ -6,7 +6,7 @@ const key = @import("key.zig");
|
|||||||
/// for a given key.
|
/// for a given key.
|
||||||
pub const Entry = struct {
|
pub const Entry = struct {
|
||||||
key: key.Key,
|
key: key.Key,
|
||||||
code: u16,
|
code: u21,
|
||||||
final: u8,
|
final: u8,
|
||||||
modifier: bool,
|
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.
|
/// 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
|
/// 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.
|
/// 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:
|
/// 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
|
/// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#functional-key-definitions
|
||||||
|
Reference in New Issue
Block a user