mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 08:16:13 +03:00
terminal: all DCS events can produce a command
This commit is contained in:
@ -21,43 +21,54 @@ pub const Handler = struct {
|
|||||||
self.discard();
|
self.discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hook(self: *Handler, alloc: Allocator, dcs: DCS) void {
|
pub fn hook(self: *Handler, alloc: Allocator, dcs: DCS) ?Command {
|
||||||
assert(self.state == .inactive);
|
assert(self.state == .inactive);
|
||||||
self.state = if (tryHook(alloc, dcs)) |state_| state: {
|
|
||||||
if (state_) |state| break :state state else {
|
// Initialize our state to ignore in case of error
|
||||||
log.info("unknown DCS hook: {}", .{dcs});
|
self.state = .{ .ignore = {} };
|
||||||
break :state .{ .ignore = {} };
|
|
||||||
}
|
// Try to parse the hook.
|
||||||
} else |err| state: {
|
const hk_ = tryHook(alloc, dcs) catch |err| {
|
||||||
log.info(
|
log.info("error initializing DCS hook, will ignore hook err={}", .{err});
|
||||||
"error initializing DCS hook, will ignore hook err={}",
|
return null;
|
||||||
.{err},
|
|
||||||
);
|
|
||||||
break :state .{ .ignore = {} };
|
|
||||||
};
|
};
|
||||||
|
const hk = hk_ orelse {
|
||||||
|
log.info("unknown DCS hook: {}", .{dcs});
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.state = hk.state;
|
||||||
|
return hk.command;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tryHook(alloc: Allocator, dcs: DCS) !?State {
|
const Hook = struct {
|
||||||
|
state: State,
|
||||||
|
command: ?Command = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn tryHook(alloc: Allocator, dcs: DCS) !?Hook {
|
||||||
return switch (dcs.intermediates.len) {
|
return switch (dcs.intermediates.len) {
|
||||||
1 => switch (dcs.intermediates[0]) {
|
1 => switch (dcs.intermediates[0]) {
|
||||||
'+' => switch (dcs.final) {
|
'+' => switch (dcs.final) {
|
||||||
// XTGETTCAP
|
// XTGETTCAP
|
||||||
// https://github.com/mitchellh/ghostty/issues/517
|
// https://github.com/mitchellh/ghostty/issues/517
|
||||||
'q' => .{
|
'q' => .{
|
||||||
|
.state = .{
|
||||||
.xtgettcap = try std.ArrayList(u8).initCapacity(
|
.xtgettcap = try std.ArrayList(u8).initCapacity(
|
||||||
alloc,
|
alloc,
|
||||||
128, // Arbitrary choice
|
128, // Arbitrary choice
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
else => null,
|
else => null,
|
||||||
},
|
},
|
||||||
|
|
||||||
'$' => switch (dcs.final) {
|
'$' => switch (dcs.final) {
|
||||||
// DECRQSS
|
// DECRQSS
|
||||||
'q' => .{
|
'q' => .{ .state = .{
|
||||||
.decrqss = .{},
|
.decrqss = .{},
|
||||||
},
|
} },
|
||||||
|
|
||||||
else => null,
|
else => null,
|
||||||
},
|
},
|
||||||
@ -222,7 +233,7 @@ test "unknown DCS command" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .final = 'A' });
|
try testing.expect(h.hook(alloc, .{ .final = 'A' }) == null);
|
||||||
try testing.expect(h.state == .ignore);
|
try testing.expect(h.state == .ignore);
|
||||||
try testing.expect(h.unhook() == null);
|
try testing.expect(h.unhook() == null);
|
||||||
try testing.expect(h.state == .inactive);
|
try testing.expect(h.state == .inactive);
|
||||||
@ -234,7 +245,7 @@ test "XTGETTCAP command" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .intermediates = "+", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "+", .final = 'q' }) == null);
|
||||||
for ("536D756C78") |byte| _ = h.put(byte);
|
for ("536D756C78") |byte| _ = h.put(byte);
|
||||||
var cmd = h.unhook().?;
|
var cmd = h.unhook().?;
|
||||||
defer cmd.deinit();
|
defer cmd.deinit();
|
||||||
@ -249,7 +260,7 @@ test "XTGETTCAP command multiple keys" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .intermediates = "+", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "+", .final = 'q' }) == null);
|
||||||
for ("536D756C78;536D756C78") |byte| _ = h.put(byte);
|
for ("536D756C78;536D756C78") |byte| _ = h.put(byte);
|
||||||
var cmd = h.unhook().?;
|
var cmd = h.unhook().?;
|
||||||
defer cmd.deinit();
|
defer cmd.deinit();
|
||||||
@ -265,7 +276,7 @@ test "XTGETTCAP command invalid data" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .intermediates = "+", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "+", .final = 'q' }) == null);
|
||||||
for ("who;536D756C78") |byte| _ = h.put(byte);
|
for ("who;536D756C78") |byte| _ = h.put(byte);
|
||||||
var cmd = h.unhook().?;
|
var cmd = h.unhook().?;
|
||||||
defer cmd.deinit();
|
defer cmd.deinit();
|
||||||
@ -281,7 +292,7 @@ test "DECRQSS command" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .intermediates = "$", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "$", .final = 'q' }) == null);
|
||||||
_ = h.put('m');
|
_ = h.put('m');
|
||||||
var cmd = h.unhook().?;
|
var cmd = h.unhook().?;
|
||||||
defer cmd.deinit();
|
defer cmd.deinit();
|
||||||
@ -295,7 +306,7 @@ test "DECRQSS invalid command" {
|
|||||||
|
|
||||||
var h: Handler = .{};
|
var h: Handler = .{};
|
||||||
defer h.deinit();
|
defer h.deinit();
|
||||||
h.hook(alloc, .{ .intermediates = "$", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "$", .final = 'q' }) == null);
|
||||||
_ = h.put('z');
|
_ = h.put('z');
|
||||||
var cmd = h.unhook().?;
|
var cmd = h.unhook().?;
|
||||||
defer cmd.deinit();
|
defer cmd.deinit();
|
||||||
@ -304,7 +315,7 @@ test "DECRQSS invalid command" {
|
|||||||
|
|
||||||
h.discard();
|
h.discard();
|
||||||
|
|
||||||
h.hook(alloc, .{ .intermediates = "$", .final = 'q' });
|
try testing.expect(h.hook(alloc, .{ .intermediates = "$", .final = 'q' }) == null);
|
||||||
_ = h.put('"');
|
_ = h.put('"');
|
||||||
_ = h.put(' ');
|
_ = h.put(' ');
|
||||||
_ = h.put('q');
|
_ = h.put('q');
|
||||||
|
@ -1860,7 +1860,9 @@ const StreamHandler = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dcsHook(self: *StreamHandler, dcs: terminal.DCS) !void {
|
pub fn dcsHook(self: *StreamHandler, dcs: terminal.DCS) !void {
|
||||||
self.dcs.hook(self.alloc, dcs);
|
var cmd = self.dcs.hook(self.alloc, dcs) orelse return;
|
||||||
|
defer cmd.deinit();
|
||||||
|
try self.dcsCommand(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dcsPut(self: *StreamHandler, byte: u8) !void {
|
pub fn dcsPut(self: *StreamHandler, byte: u8) !void {
|
||||||
|
Reference in New Issue
Block a user