From 01e1538ad329e45d760687bf71797571a6677533 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 11 Jul 2024 18:42:22 -0700 Subject: [PATCH] terminal: dcs put can return a command --- src/terminal/dcs.zig | 31 +++++++++++++++++-------------- src/termio/Exec.zig | 9 +++++++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/terminal/dcs.zig b/src/terminal/dcs.zig index cde00d218..72949789d 100644 --- a/src/terminal/dcs.zig +++ b/src/terminal/dcs.zig @@ -69,16 +69,19 @@ pub const Handler = struct { }; } - pub fn put(self: *Handler, byte: u8) void { - self.tryPut(byte) catch |err| { + /// Put a byte into the DCS handler. This will return a command + /// if a command needs to be executed. + pub fn put(self: *Handler, byte: u8) ?Command { + return self.tryPut(byte) catch |err| { // On error we just discard our state and ignore the rest log.info("error putting byte into DCS handler err={}", .{err}); self.discard(); self.state = .{ .ignore = {} }; + return null; }; } - fn tryPut(self: *Handler, byte: u8) !void { + fn tryPut(self: *Handler, byte: u8) !?Command { switch (self.state) { .inactive, .ignore, @@ -101,6 +104,8 @@ pub const Handler = struct { buffer.len += 1; }, } + + return null; } pub fn unhook(self: *Handler) ?Command { @@ -156,9 +161,7 @@ pub const Command = union(enum) { pub fn deinit(self: Command) void { switch (self) { - .xtgettcap => |*v| { - v.data.deinit(); - }, + .xtgettcap => |*v| v.data.deinit(), .decrqss => {}, } } @@ -232,7 +235,7 @@ test "XTGETTCAP command" { var h: Handler = .{}; defer h.deinit(); h.hook(alloc, .{ .intermediates = "+", .final = 'q' }); - for ("536D756C78") |byte| h.put(byte); + for ("536D756C78") |byte| _ = h.put(byte); var cmd = h.unhook().?; defer cmd.deinit(); try testing.expect(cmd == .xtgettcap); @@ -247,7 +250,7 @@ test "XTGETTCAP command multiple keys" { var h: Handler = .{}; defer h.deinit(); h.hook(alloc, .{ .intermediates = "+", .final = 'q' }); - for ("536D756C78;536D756C78") |byte| h.put(byte); + for ("536D756C78;536D756C78") |byte| _ = h.put(byte); var cmd = h.unhook().?; defer cmd.deinit(); try testing.expect(cmd == .xtgettcap); @@ -263,7 +266,7 @@ test "XTGETTCAP command invalid data" { var h: Handler = .{}; defer h.deinit(); h.hook(alloc, .{ .intermediates = "+", .final = 'q' }); - for ("who;536D756C78") |byte| h.put(byte); + for ("who;536D756C78") |byte| _ = h.put(byte); var cmd = h.unhook().?; defer cmd.deinit(); try testing.expect(cmd == .xtgettcap); @@ -279,7 +282,7 @@ test "DECRQSS command" { var h: Handler = .{}; defer h.deinit(); h.hook(alloc, .{ .intermediates = "$", .final = 'q' }); - h.put('m'); + _ = h.put('m'); var cmd = h.unhook().?; defer cmd.deinit(); try testing.expect(cmd == .decrqss); @@ -293,7 +296,7 @@ test "DECRQSS invalid command" { var h: Handler = .{}; defer h.deinit(); h.hook(alloc, .{ .intermediates = "$", .final = 'q' }); - h.put('z'); + _ = h.put('z'); var cmd = h.unhook().?; defer cmd.deinit(); try testing.expect(cmd == .decrqss); @@ -302,8 +305,8 @@ test "DECRQSS invalid command" { h.discard(); h.hook(alloc, .{ .intermediates = "$", .final = 'q' }); - h.put('"'); - h.put(' '); - h.put('q'); + _ = h.put('"'); + _ = h.put(' '); + _ = h.put('q'); try testing.expect(h.unhook() == null); } diff --git a/src/termio/Exec.zig b/src/termio/Exec.zig index 8c6212554..6b1d6d1ac 100644 --- a/src/termio/Exec.zig +++ b/src/termio/Exec.zig @@ -1864,15 +1864,20 @@ const StreamHandler = struct { } pub fn dcsPut(self: *StreamHandler, byte: u8) !void { - self.dcs.put(byte); + var cmd = self.dcs.put(byte) orelse return; + defer cmd.deinit(); + try self.dcsCommand(&cmd); } pub fn dcsUnhook(self: *StreamHandler) !void { var cmd = self.dcs.unhook() orelse return; defer cmd.deinit(); + try self.dcsCommand(&cmd); + } + fn dcsCommand(self: *StreamHandler, cmd: *terminal.dcs.Command) !void { // log.warn("DCS command: {}", .{cmd}); - switch (cmd) { + switch (cmd.*) { .xtgettcap => |*gettcap| { const map = comptime terminfo.ghostty.xtgettcapMap(); while (gettcap.next()) |key| {