mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
Merge pull request #1533 from mitchellh/shift-csi
input: encode ctrl+shift+<ascii letter> in CSIu as lowercase + shift
This commit is contained in:
@ -341,23 +341,36 @@ fn legacy(
|
|||||||
// effective mods. The fixterms spec states the shifted chars
|
// effective mods. The fixterms spec states the shifted chars
|
||||||
// should be sent uppercase but Kitty changes that behavior
|
// should be sent uppercase but Kitty changes that behavior
|
||||||
// so we'll send all the mods.
|
// so we'll send all the mods.
|
||||||
const csi_u_mods = mods: {
|
const csi_u_mods, const char = mods: {
|
||||||
|
var char: u21 = @intCast(utf8[0]);
|
||||||
var mods = CsiUMods.fromInput(self.event.mods);
|
var mods = CsiUMods.fromInput(self.event.mods);
|
||||||
|
|
||||||
|
// If our character is A to Z and we have shift set, then
|
||||||
|
// we lowercase it. This is a Kitty-specific behavior that
|
||||||
|
// we choose to follow and diverge from the fixterms spec.
|
||||||
|
// This makes it easier for programs to detect shifted letters
|
||||||
|
// for keybindings and is not just theoretical but used by
|
||||||
|
// real programs.
|
||||||
|
if (char >= 'A' and char <= 'Z' and mods.shift) {
|
||||||
|
// We want to rely on apprt to send us the correct
|
||||||
|
// unshifted codepoint...
|
||||||
|
char = @intCast(std.ascii.toLower(@intCast(char)));
|
||||||
|
}
|
||||||
|
|
||||||
// If our unshifted codepoint is identical to the shifted
|
// If our unshifted codepoint is identical to the shifted
|
||||||
// then we consider shift. Otherwise, we do not because the
|
// then we consider shift. Otherwise, we do not because the
|
||||||
// shift key was used to obtain the character. This is specified
|
// shift key was used to obtain the character. This is specified
|
||||||
// by fixterms.
|
// by fixterms.
|
||||||
if (self.event.unshifted_codepoint != @as(u21, @intCast(utf8[0]))) {
|
if (self.event.unshifted_codepoint != char) {
|
||||||
mods.shift = false;
|
mods.shift = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break :mods mods;
|
break :mods .{ mods, char };
|
||||||
};
|
};
|
||||||
const result = try std.fmt.bufPrint(
|
const result = try std.fmt.bufPrint(
|
||||||
buf,
|
buf,
|
||||||
"\x1B[{};{}u",
|
"\x1B[{};{}u",
|
||||||
.{ utf8[0], csi_u_mods.seqInt() },
|
.{ char, csi_u_mods.seqInt() },
|
||||||
);
|
);
|
||||||
// std.log.warn("CSI_U: {s}", .{result});
|
// std.log.warn("CSI_U: {s}", .{result});
|
||||||
return result;
|
return result;
|
||||||
@ -1750,6 +1763,22 @@ test "legacy: fixterm awkward letters" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These tests apply Kitty's behavior to CSIu where ctrl+shift+letter
|
||||||
|
// is sent as the unshifted letter with the shift modifier present.
|
||||||
|
test "legacy: ctrl+shift+letter ascii" {
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
{
|
||||||
|
var enc: KeyEncoder = .{ .event = .{
|
||||||
|
.key = .m,
|
||||||
|
.mods = .{ .ctrl = true, .shift = true },
|
||||||
|
.utf8 = "M",
|
||||||
|
.unshifted_codepoint = 'm',
|
||||||
|
} };
|
||||||
|
const actual = try enc.legacy(&buf);
|
||||||
|
try testing.expectEqualStrings("\x1b[109;6u", actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "legacy: shift+function key should use all mods" {
|
test "legacy: shift+function key should use all mods" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var enc: KeyEncoder = .{
|
var enc: KeyEncoder = .{
|
||||||
|
Reference in New Issue
Block a user