mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
sgr parsing can parse multiple
This commit is contained in:
@ -24,21 +24,39 @@ pub const Attribute = union(enum) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parse a set of parameters to a SGR command into an attribute.
|
/// Parser parses the attributes from a list of SGR parameters.
|
||||||
pub fn parse(params: []const u16) Attribute {
|
pub const Parser = struct {
|
||||||
// No parameters means unset
|
params: []const u16,
|
||||||
if (params.len == 0) return .{ .unset = {} };
|
idx: usize = 0,
|
||||||
|
|
||||||
switch (params[0]) {
|
/// Next returns the next attribute or null if there are no more attributes.
|
||||||
0 => if (params.len == 1) return .{ .unset = {} },
|
pub fn next(self: *Parser) ?Attribute {
|
||||||
|
if (self.idx > self.params.len) return null;
|
||||||
|
|
||||||
|
// Implicitly means unset
|
||||||
|
if (self.params.len == 0) {
|
||||||
|
self.idx += 1;
|
||||||
|
return Attribute{ .unset = {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
const slice = self.params[self.idx..self.params.len];
|
||||||
|
self.idx += 1;
|
||||||
|
|
||||||
|
// Our last one will have an idx be the last value.
|
||||||
|
if (slice.len == 0) return null;
|
||||||
|
|
||||||
|
switch (slice[0]) {
|
||||||
|
0 => return Attribute{ .unset = {} },
|
||||||
|
|
||||||
|
38 => if (slice.len >= 5 and slice[1] == 2) {
|
||||||
|
self.idx += 4;
|
||||||
|
|
||||||
38 => if ((params.len == 5 or params.len == 6) and params[1] == 2) {
|
|
||||||
// In the 6-len form, ignore the 3rd param.
|
// In the 6-len form, ignore the 3rd param.
|
||||||
const rgb = params[params.len - 3 .. params.len];
|
const rgb = slice[2..5];
|
||||||
|
|
||||||
// We use @truncate because the value should be 0 to 255. If
|
// We use @truncate because the value should be 0 to 255. If
|
||||||
// it isn't, the behavior is undefined so we just... truncate it.
|
// it isn't, the behavior is undefined so we just... truncate it.
|
||||||
return .{
|
return Attribute{
|
||||||
.direct_color_fg = .{
|
.direct_color_fg = .{
|
||||||
.r = @truncate(u8, rgb[0]),
|
.r = @truncate(u8, rgb[0]),
|
||||||
.g = @truncate(u8, rgb[1]),
|
.g = @truncate(u8, rgb[1]),
|
||||||
@ -47,13 +65,15 @@ pub fn parse(params: []const u16) Attribute {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
48 => if ((params.len == 5 or params.len == 6) and params[1] == 2) {
|
48 => if (slice.len >= 5 and slice[1] == 2) {
|
||||||
|
self.idx += 4;
|
||||||
|
|
||||||
// In the 6-len form, ignore the 3rd param.
|
// In the 6-len form, ignore the 3rd param.
|
||||||
const rgb = params[params.len - 3 .. params.len];
|
const rgb = slice[2..5];
|
||||||
|
|
||||||
// We use @truncate because the value should be 0 to 255. If
|
// We use @truncate because the value should be 0 to 255. If
|
||||||
// it isn't, the behavior is undefined so we just... truncate it.
|
// it isn't, the behavior is undefined so we just... truncate it.
|
||||||
return .{
|
return Attribute{
|
||||||
.direct_color_bg = .{
|
.direct_color_bg = .{
|
||||||
.r = @truncate(u8, rgb[0]),
|
.r = @truncate(u8, rgb[0]),
|
||||||
.g = @truncate(u8, rgb[1]),
|
.g = @truncate(u8, rgb[1]),
|
||||||
@ -65,49 +85,44 @@ pub fn parse(params: []const u16) Attribute {
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{ .unknown = params };
|
return Attribute{ .unknown = slice };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn testParse(params: []const u16) Attribute {
|
||||||
|
var p: Parser = .{ .params = params };
|
||||||
|
return p.next().?;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "sgr: parse" {
|
test "sgr: Parser" {
|
||||||
try testing.expect(parse(&[_]u16{}) == .unset);
|
try testing.expect(testParse(&[_]u16{}) == .unset);
|
||||||
try testing.expect(parse(&[_]u16{0}) == .unset);
|
try testing.expect(testParse(&[_]u16{0}) == .unset);
|
||||||
try testing.expect(parse(&[_]u16{ 0, 1 }) == .unknown);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const v = parse(&[_]u16{ 38, 2, 40, 44, 52 });
|
const v = testParse(&[_]u16{ 38, 2, 40, 44, 52 });
|
||||||
try testing.expect(v == .direct_color_fg);
|
try testing.expect(v == .direct_color_fg);
|
||||||
try testing.expectEqual(@as(u8, 40), v.direct_color_fg.r);
|
try testing.expectEqual(@as(u8, 40), v.direct_color_fg.r);
|
||||||
try testing.expectEqual(@as(u8, 44), v.direct_color_fg.g);
|
try testing.expectEqual(@as(u8, 44), v.direct_color_fg.g);
|
||||||
try testing.expectEqual(@as(u8, 52), v.direct_color_fg.b);
|
try testing.expectEqual(@as(u8, 52), v.direct_color_fg.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
try testing.expect(testParse(&[_]u16{ 38, 2, 44, 52 }) == .unknown);
|
||||||
const v = parse(&[_]u16{ 38, 2, 22, 40, 44, 52 });
|
|
||||||
try testing.expect(v == .direct_color_fg);
|
|
||||||
try testing.expectEqual(@as(u8, 40), v.direct_color_fg.r);
|
|
||||||
try testing.expectEqual(@as(u8, 44), v.direct_color_fg.g);
|
|
||||||
try testing.expectEqual(@as(u8, 52), v.direct_color_fg.b);
|
|
||||||
}
|
|
||||||
|
|
||||||
try testing.expect(parse(&[_]u16{ 38, 2, 44, 52 }) == .unknown);
|
|
||||||
try testing.expect(parse(&[_]u16{ 38, 2, 22, 22, 40, 44, 52 }) == .unknown);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const v = parse(&[_]u16{ 48, 2, 40, 44, 52 });
|
const v = testParse(&[_]u16{ 48, 2, 40, 44, 52 });
|
||||||
try testing.expect(v == .direct_color_bg);
|
try testing.expect(v == .direct_color_bg);
|
||||||
try testing.expectEqual(@as(u8, 40), v.direct_color_bg.r);
|
try testing.expectEqual(@as(u8, 40), v.direct_color_bg.r);
|
||||||
try testing.expectEqual(@as(u8, 44), v.direct_color_bg.g);
|
try testing.expectEqual(@as(u8, 44), v.direct_color_bg.g);
|
||||||
try testing.expectEqual(@as(u8, 52), v.direct_color_bg.b);
|
try testing.expectEqual(@as(u8, 52), v.direct_color_bg.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
try testing.expect(testParse(&[_]u16{ 48, 2, 44, 52 }) == .unknown);
|
||||||
const v = parse(&[_]u16{ 48, 2, 22, 40, 44, 52 });
|
|
||||||
try testing.expect(v == .direct_color_bg);
|
|
||||||
try testing.expectEqual(@as(u8, 40), v.direct_color_bg.r);
|
|
||||||
try testing.expectEqual(@as(u8, 44), v.direct_color_bg.g);
|
|
||||||
try testing.expectEqual(@as(u8, 52), v.direct_color_bg.b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try testing.expect(parse(&[_]u16{ 48, 2, 44, 52 }) == .unknown);
|
test "sgr: Parser multiple" {
|
||||||
try testing.expect(parse(&[_]u16{ 48, 2, 22, 22, 40, 44, 52 }) == .unknown);
|
var p: Parser = .{ .params = &[_]u16{ 0, 38, 2, 40, 44, 52 } };
|
||||||
|
try testing.expect(p.next().? == .unset);
|
||||||
|
try testing.expect(p.next().? == .direct_color_fg);
|
||||||
|
try testing.expect(p.next() == null);
|
||||||
|
try testing.expect(p.next() == null);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user