mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
input: lot more Kitty encoding logic
This commit is contained in:
@ -41,7 +41,7 @@ pub fn kitty(
|
|||||||
const binding_mods = effective_mods.binding();
|
const binding_mods = effective_mods.binding();
|
||||||
|
|
||||||
// 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: {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -49,38 +49,75 @@ pub fn kitty(
|
|||||||
break :entry null;
|
break :entry null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Quote:
|
preprocessing: {
|
||||||
// The only exceptions are the Enter, Tab and Backspace keys which
|
// When composing, the only keys sent are plain modifiers.
|
||||||
// still generate the same bytes as in legacy mode this is to allow the
|
if (self.event.composing) {
|
||||||
// user to type and execute commands in the shell such as reset after a
|
if (entry_) |entry| {
|
||||||
// program that sets this mode crashes without clearing it.
|
if (entry.modifier) break :preprocessing;
|
||||||
if (effective_mods.empty()) {
|
}
|
||||||
switch (self.event.key) {
|
|
||||||
.enter => return try copyToBuf(buf, "\r"),
|
return "";
|
||||||
.tab => return try copyToBuf(buf, "\t"),
|
}
|
||||||
.backspace => return try copyToBuf(buf, "\x7F"),
|
|
||||||
else => {},
|
// If we're reporting all then we always send CSI sequences.
|
||||||
|
if (!self.kitty_flags.report_all) {
|
||||||
|
// Quote:
|
||||||
|
// The only exceptions are the Enter, Tab and Backspace keys which
|
||||||
|
// still generate the same bytes as in legacy mode this is to allow the
|
||||||
|
// user to type and execute commands in the shell such as reset after a
|
||||||
|
// program that sets this mode crashes without clearing it.
|
||||||
|
//
|
||||||
|
// Quote ("report all" mode):
|
||||||
|
// Note that all keys are reported as escape codes, including Enter,
|
||||||
|
// Tab, Backspace etc.
|
||||||
|
if (effective_mods.empty()) {
|
||||||
|
switch (self.event.key) {
|
||||||
|
.enter => return try copyToBuf(buf, "\r"),
|
||||||
|
.tab => return try copyToBuf(buf, "\t"),
|
||||||
|
.backspace => return try copyToBuf(buf, "\x7F"),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send plain-text non-modified text directly to the terminal.
|
||||||
|
// We don't send release events because those are specially encoded.
|
||||||
|
if (self.event.utf8.len > 0 and
|
||||||
|
binding_mods.empty() and
|
||||||
|
self.event.action != .release)
|
||||||
|
{
|
||||||
|
return try copyToBuf(buf, self.event.utf8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send plain-text non-modified text directly to the terminal.
|
const final_entry = entry_ orelse {
|
||||||
// We don't send release events because those are specially encoded.
|
|
||||||
if (self.event.utf8.len > 0 and
|
|
||||||
binding_mods.empty() and
|
|
||||||
self.event.action != .release)
|
|
||||||
{
|
|
||||||
return try copyToBuf(buf, self.event.utf8);
|
|
||||||
}
|
|
||||||
|
|
||||||
const kitty_mods = KittyMods.fromInput(all_mods);
|
|
||||||
const final_entry = entry orelse {
|
|
||||||
// TODO: we need to look it up
|
// TODO: we need to look it up
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
_ = kitty_mods;
|
|
||||||
_ = final_entry;
|
|
||||||
|
|
||||||
return "X";
|
const seq: KittySequence = seq: {
|
||||||
|
var seq: KittySequence = .{
|
||||||
|
.key = final_entry.code,
|
||||||
|
.final = final_entry.final,
|
||||||
|
.mods = KittyMods.fromInput(all_mods),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (self.kitty_flags.report_events) {
|
||||||
|
seq.event = switch (self.event.action) {
|
||||||
|
.press => .press,
|
||||||
|
.release => .release,
|
||||||
|
.repeat => .repeat,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.kitty_flags.report_associated) {
|
||||||
|
seq.text = self.event.utf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
break :seq seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
return try seq.encode(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform legacy encoding of the key event. "Legacy" in this case
|
/// Perform legacy encoding of the key event. "Legacy" in this case
|
||||||
@ -477,9 +514,9 @@ const KittyMods = packed struct(u8) {
|
|||||||
const KittySequence = struct {
|
const KittySequence = struct {
|
||||||
key: u16,
|
key: u16,
|
||||||
final: u8,
|
final: u8,
|
||||||
|
mods: KittyMods = .{},
|
||||||
event: Event = .none,
|
event: Event = .none,
|
||||||
alternates: []const u16 = &.{},
|
alternates: []const u16 = &.{},
|
||||||
mods: KittyMods = .{},
|
|
||||||
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).
|
||||||
@ -701,6 +738,36 @@ test "kitty: enter, backspace, tab" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "kitty: composing with no modifier" {
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
var enc: KeyEncoder = .{
|
||||||
|
.event = .{
|
||||||
|
.key = .a,
|
||||||
|
.mods = .{ .shift = true },
|
||||||
|
.composing = true,
|
||||||
|
},
|
||||||
|
.kitty_flags = .{ .disambiguate = true },
|
||||||
|
};
|
||||||
|
|
||||||
|
const actual = try enc.kitty(&buf);
|
||||||
|
try testing.expectEqualStrings("", actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "kitty: composing with modifier" {
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
var enc: KeyEncoder = .{
|
||||||
|
.event = .{
|
||||||
|
.key = .left_shift,
|
||||||
|
.mods = .{ .shift = true },
|
||||||
|
.composing = true,
|
||||||
|
},
|
||||||
|
.kitty_flags = .{ .disambiguate = true },
|
||||||
|
};
|
||||||
|
|
||||||
|
const actual = try enc.kitty(&buf);
|
||||||
|
try testing.expectEqualStrings("\x1b[57441;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 = .{
|
||||||
|
Reference in New Issue
Block a user