fix(terminal): correct SGR direct color parsing

This commit is contained in:
Qwerasd
2024-12-31 14:37:23 -05:00
parent 5ba8fee38a
commit 4543cdeac8

View File

@ -189,26 +189,39 @@ pub const Parser = struct {
.@"8_fg" = @enumFromInt(slice[0] - 30), .@"8_fg" = @enumFromInt(slice[0] - 30),
}, },
38 => if (slice.len >= 5 and slice[1] == 2) { 38 => if (slice.len >= 2) switch (slice[1]) {
self.idx += 4; // `2` indicates direct-color (r, g, b).
// We need at least 3 more params for this to make sense.
2 => if (slice.len >= 5) {
self.idx += 4;
// When a colon separator is used, there may or may not be
// a color space identifier as the third param, which we
// need to ignore (it has no standardized behavior).
const rgb = if (slice.len == 5 or !self.colon)
slice[2..5]
else rgb: {
self.idx += 1;
break :rgb slice[3..6];
};
// In the 6-len form, ignore the 3rd param. // We use @truncate because the value should be 0 to 255. If
const rgb = slice[2..5]; // it isn't, the behavior is undefined so we just... truncate it.
return Attribute{
// We use @truncate because the value should be 0 to 255. If .direct_color_fg = .{
// it isn't, the behavior is undefined so we just... truncate it. .r = @truncate(rgb[0]),
return Attribute{ .g = @truncate(rgb[1]),
.direct_color_fg = .{ .b = @truncate(rgb[2]),
.r = @truncate(rgb[0]), },
.g = @truncate(rgb[1]), };
.b = @truncate(rgb[2]), },
}, // `5` indicates indexed color.
}; 5 => if (slice.len >= 3) {
} else if (slice.len >= 3 and slice[1] == 5) { self.idx += 2;
self.idx += 2; return Attribute{
return Attribute{ .@"256_fg" = @truncate(slice[2]),
.@"256_fg" = @truncate(slice[2]), };
}; },
else => {},
}, },
39 => return Attribute{ .reset_fg = {} }, 39 => return Attribute{ .reset_fg = {} },
@ -217,26 +230,39 @@ pub const Parser = struct {
.@"8_bg" = @enumFromInt(slice[0] - 40), .@"8_bg" = @enumFromInt(slice[0] - 40),
}, },
48 => if (slice.len >= 5 and slice[1] == 2) { 48 => if (slice.len >= 2) switch (slice[1]) {
self.idx += 4; // `2` indicates direct-color (r, g, b).
// We need at least 3 more params for this to make sense.
2 => if (slice.len >= 5) {
self.idx += 4;
// When a colon separator is used, there may or may not be
// a color space identifier as the third param, which we
// need to ignore (it has no standardized behavior).
const rgb = if (slice.len == 5 or !self.colon)
slice[2..5]
else rgb: {
self.idx += 1;
break :rgb slice[3..6];
};
// We only support the 5-len form. // We use @truncate because the value should be 0 to 255. If
const rgb = slice[2..5]; // it isn't, the behavior is undefined so we just... truncate it.
return Attribute{
// We use @truncate because the value should be 0 to 255. If .direct_color_bg = .{
// it isn't, the behavior is undefined so we just... truncate it. .r = @truncate(rgb[0]),
return Attribute{ .g = @truncate(rgb[1]),
.direct_color_bg = .{ .b = @truncate(rgb[2]),
.r = @truncate(rgb[0]), },
.g = @truncate(rgb[1]), };
.b = @truncate(rgb[2]), },
}, // `5` indicates indexed color.
}; 5 => if (slice.len >= 3) {
} else if (slice.len >= 3 and slice[1] == 5) { self.idx += 2;
self.idx += 2; return Attribute{
return Attribute{ .@"256_bg" = @truncate(slice[2]),
.@"256_bg" = @truncate(slice[2]), };
}; },
else => {},
}, },
49 => return Attribute{ .reset_bg = {} }, 49 => return Attribute{ .reset_bg = {} },
@ -244,30 +270,39 @@ pub const Parser = struct {
53 => return Attribute{ .overline = {} }, 53 => return Attribute{ .overline = {} },
55 => return Attribute{ .reset_overline = {} }, 55 => return Attribute{ .reset_overline = {} },
58 => if (slice.len >= 5 and slice[1] == 2) { 58 => if (slice.len >= 2) switch (slice[1]) {
self.idx += 4; // `2` indicates direct-color (r, g, b).
// We need at least 3 more params for this to make sense.
2 => if (slice.len >= 5) {
self.idx += 4;
// When a colon separator is used, there may or may not be
// a color space identifier as the third param, which we
// need to ignore (it has no standardized behavior).
const rgb = if (slice.len == 5 or !self.colon)
slice[2..5]
else rgb: {
self.idx += 1;
break :rgb slice[3..6];
};
// In the 6-len form, ignore the 3rd param. Otherwise, use it. // We use @truncate because the value should be 0 to 255. If
const rgb = if (slice.len == 5) slice[2..5] else rgb: { // it isn't, the behavior is undefined so we just... truncate it.
// Consume one more element return Attribute{
self.idx += 1; .underline_color = .{
break :rgb slice[3..6]; .r = @truncate(rgb[0]),
}; .g = @truncate(rgb[1]),
.b = @truncate(rgb[2]),
// 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 Attribute{ },
.underline_color = .{ // `5` indicates indexed color.
.r = @truncate(rgb[0]), 5 => if (slice.len >= 3) {
.g = @truncate(rgb[1]), self.idx += 2;
.b = @truncate(rgb[2]), return Attribute{
}, .@"256_underline_color" = @truncate(slice[2]),
}; };
} else if (slice.len >= 3 and slice[1] == 5) { },
self.idx += 2; else => {},
return Attribute{
.@"256_underline_color" = @truncate(slice[2]),
};
}, },
59 => return Attribute{ .reset_underline_color = {} }, 59 => return Attribute{ .reset_underline_color = {} },