mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +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.
|
||||
pub fn parse(params: []const u16) Attribute {
|
||||
// No parameters means unset
|
||||
if (params.len == 0) return .{ .unset = {} };
|
||||
/// Parser parses the attributes from a list of SGR parameters.
|
||||
pub const Parser = struct {
|
||||
params: []const u16,
|
||||
idx: usize = 0,
|
||||
|
||||
switch (params[0]) {
|
||||
0 => if (params.len == 1) return .{ .unset = {} },
|
||||
/// Next returns the next attribute or null if there are no more attributes.
|
||||
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.
|
||||
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
|
||||
// it isn't, the behavior is undefined so we just... truncate it.
|
||||
return .{
|
||||
return Attribute{
|
||||
.direct_color_fg = .{
|
||||
.r = @truncate(u8, rgb[0]),
|
||||
.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.
|
||||
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
|
||||
// it isn't, the behavior is undefined so we just... truncate it.
|
||||
return .{
|
||||
return Attribute{
|
||||
.direct_color_bg = .{
|
||||
.r = @truncate(u8, rgb[0]),
|
||||
.g = @truncate(u8, rgb[1]),
|
||||
@ -65,49 +85,44 @@ pub fn parse(params: []const u16) Attribute {
|
||||
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" {
|
||||
try testing.expect(parse(&[_]u16{}) == .unset);
|
||||
try testing.expect(parse(&[_]u16{0}) == .unset);
|
||||
try testing.expect(parse(&[_]u16{ 0, 1 }) == .unknown);
|
||||
test "sgr: Parser" {
|
||||
try testing.expect(testParse(&[_]u16{}) == .unset);
|
||||
try testing.expect(testParse(&[_]u16{0}) == .unset);
|
||||
|
||||
{
|
||||
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.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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
try testing.expect(testParse(&[_]u16{ 38, 2, 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.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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
try testing.expect(parse(&[_]u16{ 48, 2, 22, 22, 40, 44, 52 }) == .unknown);
|
||||
try testing.expect(testParse(&[_]u16{ 48, 2, 44, 52 }) == .unknown);
|
||||
}
|
||||
|
||||
test "sgr: Parser multiple" {
|
||||
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