mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
Merge pull request #2669 from ghostty-org/push-tmluvvwsqqot
terminal: parse CSI t 22/23 for push/pop title
This commit is contained in:
@ -40,3 +40,11 @@ pub const SizeReportStyle = enum {
|
||||
csi_18_t,
|
||||
csi_21_t,
|
||||
};
|
||||
|
||||
/// XTWINOPS CSI 22/23
|
||||
pub const TitlePushPop = struct {
|
||||
op: Op,
|
||||
index: u16,
|
||||
|
||||
pub const Op = enum { push, pop };
|
||||
};
|
||||
|
@ -1162,6 +1162,33 @@ pub fn Stream(comptime Handler: type) type {
|
||||
"ignoring CSI 21 t with extra parameters: {s}",
|
||||
.{input},
|
||||
),
|
||||
inline 22, 23 => |number| if ((input.params.len == 2 or
|
||||
input.params.len == 3) and
|
||||
// we only support window title
|
||||
(input.params[1] == 0 or
|
||||
input.params[1] == 2))
|
||||
{
|
||||
// push/pop title
|
||||
if (@hasDecl(T, "pushPopTitle")) {
|
||||
self.handler.pushPopTitle(.{
|
||||
.op = switch (number) {
|
||||
22 => .push,
|
||||
23 => .pop,
|
||||
else => @compileError("unreachable"),
|
||||
},
|
||||
.index = if (input.params.len == 3)
|
||||
input.params[2]
|
||||
else
|
||||
0,
|
||||
});
|
||||
} else log.warn(
|
||||
"ignoring unimplemented CSI 22/23 t",
|
||||
.{},
|
||||
);
|
||||
} else log.warn(
|
||||
"ignoring CSI 22/23 t with extra parameters: {s}",
|
||||
.{input},
|
||||
),
|
||||
else => log.warn(
|
||||
"ignoring CSI t with unimplemented parameter: {s}",
|
||||
.{input},
|
||||
@ -2162,3 +2189,141 @@ test "stream: invalid CSI t" {
|
||||
try s.nextSlice("\x1b[19t");
|
||||
try testing.expectEqual(null, s.handler.style);
|
||||
}
|
||||
|
||||
test "stream: CSI t push title" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[22;0t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .push,
|
||||
.index = 0,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
||||
test "stream: CSI t push title with explicit window" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[22;2t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .push,
|
||||
.index = 0,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
||||
test "stream: CSI t push title with explicit icon" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[22;1t");
|
||||
try testing.expectEqual(null, s.handler.op);
|
||||
}
|
||||
|
||||
test "stream: CSI t push title with index" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[22;0;5t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .push,
|
||||
.index = 5,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
||||
test "stream: CSI t pop title" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[23;0t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .pop,
|
||||
.index = 0,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
||||
test "stream: CSI t pop title with explicit window" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[23;2t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .pop,
|
||||
.index = 0,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
||||
test "stream: CSI t pop title with explicit icon" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[23;1t");
|
||||
try testing.expectEqual(null, s.handler.op);
|
||||
}
|
||||
|
||||
test "stream: CSI t pop title with index" {
|
||||
const H = struct {
|
||||
op: ?csi.TitlePushPop = null,
|
||||
|
||||
pub fn pushPopTitle(self: *@This(), op: csi.TitlePushPop) void {
|
||||
self.op = op;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
|
||||
try s.nextSlice("\x1b[23;0;5t");
|
||||
try testing.expectEqual(csi.TitlePushPop{
|
||||
.op = .pop,
|
||||
.index = 5,
|
||||
}, s.handler.op.?);
|
||||
}
|
||||
|
Reference in New Issue
Block a user