mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
core: process fixterms sequences for modified unicode characters
This commit is contained in:
@ -1081,6 +1081,27 @@ pub fn charCallback(
|
||||
}
|
||||
}
|
||||
|
||||
// Let's see if we should apply fixterms to this codepoint.
|
||||
// At this stage of key processing, we only need to apply fixterms
|
||||
// to unicode codepoints (the point of charCallback) if we have
|
||||
// ctrl set.
|
||||
if (mods.ctrl) {
|
||||
const csi_u_mods = terminal.csi_u.Mods.fromInput(mods);
|
||||
const resp = try std.fmt.bufPrint(
|
||||
&data,
|
||||
"\x1B[{};{}u",
|
||||
.{ codepoint, csi_u_mods.seqInt() },
|
||||
);
|
||||
_ = self.io_thread.mailbox.push(.{
|
||||
.write_small = .{
|
||||
.data = data,
|
||||
.len = @intCast(resp.len),
|
||||
},
|
||||
}, .{ .forever = {} });
|
||||
try self.io_thread.wakeup.notify();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prefix our data with ESC if we have alt pressed.
|
||||
var i: u8 = 0;
|
||||
if (mods.alt) alt: {
|
||||
|
64
src/terminal/csi_u.zig
Normal file
64
src/terminal/csi_u.zig
Normal file
@ -0,0 +1,64 @@
|
||||
//! This file has information related to Paul Evans's "fixterms"
|
||||
//! encoding, also sometimes referred to as "CSI u" encoding.
|
||||
//!
|
||||
//! https://www.leonerd.org.uk/hacks/fixterms/
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const input = @import("../input.zig");
|
||||
|
||||
pub const Mods = packed struct(u3) {
|
||||
shift: bool = false,
|
||||
alt: bool = false,
|
||||
ctrl: bool = false,
|
||||
|
||||
/// Convert an input mods value into the CSI u mods value.
|
||||
pub fn fromInput(mods: input.Mods) Mods {
|
||||
return .{
|
||||
.shift = mods.shift,
|
||||
.alt = mods.alt,
|
||||
.ctrl = mods.ctrl,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the raw int value of this packed struct.
|
||||
pub fn int(self: Mods) u3 {
|
||||
return @bitCast(self);
|
||||
}
|
||||
|
||||
/// Returns the integer value sent as part of the CSI u sequence.
|
||||
/// This adds 1 to the bitmask value as described in the spec.
|
||||
pub fn seqInt(self: Mods) u4 {
|
||||
const raw: u4 = @intCast(self.int());
|
||||
return raw + 1;
|
||||
}
|
||||
};
|
||||
|
||||
test "modifer sequence values" {
|
||||
// This is all sort of trivially seen by looking at the code but
|
||||
// we want to make sure we never regress this.
|
||||
const testing = std.testing;
|
||||
var mods: Mods = .{};
|
||||
try testing.expectEqual(@as(u4, 1), mods.seqInt());
|
||||
|
||||
mods = .{ .shift = true };
|
||||
try testing.expectEqual(@as(u4, 2), mods.seqInt());
|
||||
|
||||
mods = .{ .alt = true };
|
||||
try testing.expectEqual(@as(u4, 3), mods.seqInt());
|
||||
|
||||
mods = .{ .ctrl = true };
|
||||
try testing.expectEqual(@as(u4, 5), mods.seqInt());
|
||||
|
||||
mods = .{ .alt = true, .shift = true };
|
||||
try testing.expectEqual(@as(u4, 4), mods.seqInt());
|
||||
|
||||
mods = .{ .ctrl = true, .shift = true };
|
||||
try testing.expectEqual(@as(u4, 6), mods.seqInt());
|
||||
|
||||
mods = .{ .alt = true, .ctrl = true };
|
||||
try testing.expectEqual(@as(u4, 7), mods.seqInt());
|
||||
|
||||
mods = .{ .alt = true, .ctrl = true, .shift = true };
|
||||
try testing.expectEqual(@as(u4, 8), mods.seqInt());
|
||||
}
|
@ -7,6 +7,7 @@ const csi = @import("csi.zig");
|
||||
const sgr = @import("sgr.zig");
|
||||
pub const point = @import("point.zig");
|
||||
pub const color = @import("color.zig");
|
||||
pub const csi_u = @import("csi_u.zig");
|
||||
pub const modes = @import("modes.zig");
|
||||
pub const parse_table = @import("parse_table.zig");
|
||||
|
||||
|
Reference in New Issue
Block a user