terminal: stylistic tweaks to kitty color protocol parsing

This commit is contained in:
Mitchell Hashimoto
2024-08-20 23:21:03 -04:00
parent f4b2925434
commit 3b2ed40854

View File

@ -370,15 +370,18 @@ pub const Parser = struct {
self.buf_start = 0; self.buf_start = 0;
self.buf_idx = 0; self.buf_idx = 0;
self.complete = false; self.complete = false;
if (self.command == .kitty_color_protocol) {
self.command.kitty_color_protocol.list.deinit();
}
if (self.buf_dynamic) |ptr| { if (self.buf_dynamic) |ptr| {
const alloc = self.alloc.?; const alloc = self.alloc.?;
ptr.deinit(alloc); ptr.deinit(alloc);
alloc.destroy(ptr); alloc.destroy(ptr);
self.buf_dynamic = null; self.buf_dynamic = null;
} }
// Some commands have their own memory management we need to clear.
switch (self.command) {
.kitty_color_protocol => |*v| v.list.deinit(),
else => {},
}
} }
/// Consume the next character c and advance the parser state. /// Consume the next character c and advance the parser state.
@ -502,10 +505,16 @@ pub const Parser = struct {
}, },
.@"21" => switch (c) { .@"21" => switch (c) {
';' => { ';' => kitty: {
const alloc = self.alloc orelse {
log.info("OSC 21 requires an allocator, but none was provided", .{});
self.state = .invalid;
break :kitty;
};
self.command = .{ self.command = .{
.kitty_color_protocol = .{ .kitty_color_protocol = .{
.list = std.ArrayList(Command.KittyColorProtocol.Request).init(self.alloc.?), .list = std.ArrayList(Command.KittyColorProtocol.Request).init(alloc),
}, },
}; };
@ -1032,19 +1041,19 @@ pub const Parser = struct {
return; return;
} }
const key = key: { // For our key, we first try to parse it as a special key. If that
break :key std.meta.stringToEnum(Command.KittyColorProtocol.Kind, self.temp_state.key) orelse { // doesn't work then we try to parse it as a number for a palette.
const v = std.fmt.parseUnsigned(u9, self.temp_state.key, 10) catch { const key: Command.KittyColorProtocol.Kind = std.meta.stringToEnum(
log.warn("unknown key in kitty color protocol: {s}", .{self.temp_state.key}); Command.KittyColorProtocol.Kind,
return; self.temp_state.key,
}; ) orelse @enumFromInt(std.fmt.parseUnsigned(
if (v > 255) { u8,
log.warn("unknown key in kitty color protocol: {s}", .{self.temp_state.key}); self.temp_state.key,
return; 10,
} ) catch {
break :key @as(Command.KittyColorProtocol.Kind, @enumFromInt(v)); log.warn("unknown key in kitty color protocol: {s}", .{self.temp_state.key});
}; return;
}; });
const value = value: { const value = value: {
if (self.buf_start == self.buf_idx) break :value ""; if (self.buf_start == self.buf_idx) break :value "";
@ -1054,34 +1063,25 @@ pub const Parser = struct {
switch (self.command) { switch (self.command) {
.kitty_color_protocol => |*v| { .kitty_color_protocol => |*v| {
// Cap our allocation amount for our list.
if (v.list.items.len >= @as(usize, Command.KittyColorProtocol.Kind.max) * 2) { if (v.list.items.len >= @as(usize, Command.KittyColorProtocol.Kind.max) * 2) {
self.state = .invalid; self.state = .invalid;
log.warn("exceeded limit for number of keys in kitty color protocol, ignoring", .{}); log.warn("exceeded limit for number of keys in kitty color protocol, ignoring", .{});
return; return;
} }
if (kind == .key_only) {
if (kind == .key_only or value.len == 0) {
v.list.append(.{ .reset = key }) catch |err| { v.list.append(.{ .reset = key }) catch |err| {
log.warn("unable to append kitty color protocol option: {}", .{err}); log.warn("unable to append kitty color protocol option: {}", .{err});
return; return;
}; };
return; } else if (mem.eql(u8, "?", value)) {
}
if (value.len == 0) {
v.list.append(.{ .reset = key }) catch |err| {
log.warn("unable to append kitty color protocol option: {}", .{err});
return;
};
return;
}
if (mem.eql(u8, "?", value)) {
v.list.append(.{ .query = key }) catch |err| { v.list.append(.{ .query = key }) catch |err| {
log.warn("unable to append kitty color protocol option: {}", .{err}); log.warn("unable to append kitty color protocol option: {}", .{err});
return; return;
}; };
return; } else {
} v.list.append(.{
v.list.append(
.{
.set = .{ .set = .{
.key = key, .key = key,
.color = RGB.parse(value) catch |err| switch (err) { .color = RGB.parse(value) catch |err| switch (err) {
@ -1091,12 +1091,11 @@ pub const Parser = struct {
}, },
}, },
}, },
}, }) catch |err| {
) catch |err| { log.warn("unable to append kitty color protocol option: {}", .{err});
log.warn("unable to append kitty color protocol option: {}", .{err}); return;
return; };
}; }
return;
}, },
else => {}, else => {},
} }
@ -1738,6 +1737,17 @@ test "OSC: kitty color protocol" {
} }
} }
test "OSC: kitty color protocol without allocator" {
const testing = std.testing;
var p: Parser = .{};
defer p.deinit();
const input = "21;foreground=?";
for (input) |ch| p.next(ch);
try testing.expect(p.end('\x1b') == null);
}
test "OSC: kitty color protocol kind" { test "OSC: kitty color protocol kind" {
const info = @typeInfo(Command.KittyColorProtocol.Kind); const info = @typeInfo(Command.KittyColorProtocol.Kind);