From b26c42f4a64d9fdb686c3678d08b4ce31b3f7fd6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Dec 2025 14:28:00 -0800 Subject: [PATCH] terminal/tmux: better formatting for notifications and actions --- src/terminal/tmux/control.zig | 26 +++++++++++++++++++++++++- src/terminal/tmux/viewer.zig | 24 ++++++++++++++++++++++++ src/termio/stream_handler.zig | 6 +++--- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/terminal/tmux/control.zig b/src/terminal/tmux/control.zig index 3624173dd..79ed530ec 100644 --- a/src/terminal/tmux/control.zig +++ b/src/terminal/tmux/control.zig @@ -531,7 +531,31 @@ pub const Notification = union(enum) { session_id: usize, name: []const u8, }, -}; + + pub fn format(self: Notification, writer: *std.Io.Writer) !void { + const T = Notification; + const info = @typeInfo(T).@"union"; + + try writer.writeAll(@typeName(T)); + if (info.tag_type) |TagType| { + try writer.writeAll("{ ."); + try writer.writeAll(@tagName(@as(TagType, self))); + try writer.writeAll(" = "); + + inline for (info.fields) |u_field| { + if (self == @field(TagType, u_field.name)) { + const value = @field(self, u_field.name); + switch (u_field.type) { + []const u8 => try writer.print("\"{s}\"", .{std.mem.trim(u8, value, " \t\r\n")}), + else => try writer.print("{any}", .{value}), + } + } + } + + try writer.writeAll(" }"); + } + } + }; test "tmux begin/end empty" { const testing = std.testing; diff --git a/src/terminal/tmux/viewer.zig b/src/terminal/tmux/viewer.zig index dc3fdbcfa..32da1b4e4 100644 --- a/src/terminal/tmux/viewer.zig +++ b/src/terminal/tmux/viewer.zig @@ -64,6 +64,30 @@ pub const Viewer = struct { /// are guaranteed to be stable. Additionally, tmux (as of Dec 2025) /// never re-uses window IDs within a server process lifetime. windows: []const Window, + + pub fn format(self: Action, writer: *std.Io.Writer) !void { + const T = Action; + const info = @typeInfo(T).@"union"; + + try writer.writeAll(@typeName(T)); + if (info.tag_type) |TagType| { + try writer.writeAll("{ ."); + try writer.writeAll(@tagName(@as(TagType, self))); + try writer.writeAll(" = "); + + inline for (info.fields) |u_field| { + if (self == @field(TagType, u_field.name)) { + const value = @field(self, u_field.name); + switch (u_field.type) { + []const u8 => try writer.print("\"{s}\"", .{std.mem.trim(u8, value, " \t\r\n")}), + else => try writer.print("{any}", .{value}), + } + } + } + + try writer.writeAll(" }"); + } + } }; pub const Input = union(enum) { diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index be5cb6418..8218315be 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -384,7 +384,7 @@ pub const StreamHandler = struct { // If tmux control mode is disabled at the build level, // then this whole block shouldn't be analyzed. if (comptime !tmux_enabled) break :tmux; - log.info("tmux control mode event cmd={}", .{tmux}); + log.info("tmux control mode event cmd={f}", .{tmux}); switch (tmux) { .enter => { @@ -415,7 +415,7 @@ pub const StreamHandler = struct { // This can only really happen if we failed to // initialize the viewer on enter. log.info( - "received tmux control mode command without viewer: {}", + "received tmux control mode command without viewer: {f}", .{tmux}, ); @@ -423,7 +423,7 @@ pub const StreamHandler = struct { }; for (try viewer.next(.{ .tmux = tmux })) |action| { - log.info("tmux viewer action={}", .{action}); + log.info("tmux viewer action={f}", .{action}); switch (action) { .exit => { // We ignore this because we will fully exit when