terminal/tmux: capture visible area after history

pull/9860/head
Mitchell Hashimoto 2025-12-09 11:19:47 -08:00
parent 41bf541005
commit b7fe9a926d
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
1 changed files with 65 additions and 1 deletions

View File

@ -369,6 +369,11 @@ pub const Viewer = struct {
id,
content,
),
.pane_visible => |id| try self.receivedPaneVisible(
id,
content,
),
}
// After processing commands, we add our next command to
@ -489,6 +494,7 @@ pub const Viewer = struct {
if (self.panes.contains(pane_id)) continue;
try self.queueCommands(&.{
.{ .pane_history = pane_id },
.{ .pane_visible = pane_id },
});
}
}
@ -542,6 +548,31 @@ pub const Viewer = struct {
};
}
fn receivedPaneVisible(
self: *Viewer,
id: usize,
content: []const u8,
) !void {
// Get our pane
const entry = self.panes.getEntry(id) orelse {
log.info("received pane visible for untracked pane id={}", .{id});
return;
};
const pane: *Pane = entry.value_ptr;
// Erase the active area and reset the cursor to the top-left
// before writing the visible content.
pane.terminal.eraseDisplay(.complete, false);
pane.terminal.setCursorPos(1, 1);
var stream = pane.terminal.vtStream();
defer stream.deinit();
stream.nextSlice(content) catch |err| {
log.info("failed to process pane visible for pane id={}: {}", .{ id, err });
return err;
};
}
fn initLayout(
gpa_alloc: Allocator,
panes_old: *const PanesMap,
@ -681,6 +712,9 @@ const Command = union(enum) {
/// Capture history for the given pane ID.
pane_history: usize,
/// Capture visible area for the given pane ID.
pane_visible: usize,
/// User command. This is a command provided by the user. Since
/// this is user provided, we can't be sure what it is.
user: []const u8,
@ -689,6 +723,7 @@ const Command = union(enum) {
return switch (self) {
.list_windows,
.pane_history,
.pane_visible,
=> {},
.user => |v| alloc.free(v),
};
@ -718,6 +753,15 @@ const Command = union(enum) {
.{id},
),
.pane_visible => |id| try writer.print(
// -p = output to stdout instead of buffer
// -e = output escape sequences for SGR
// -t %{d} = target a specific pane ID
// (no -S/-E = capture visible area only)
"capture-pane -p -e -t %{d}\n",
.{id},
),
.user => |v| try writer.writeAll(v),
}
}
@ -888,7 +932,27 @@ test "initial flow" {
\\
,
} },
// Moves on to the next pane
// Moves on to pane_visible for pane 0
.contains_command = "capture-pane",
.check_command = (struct {
fn check(_: *Viewer, command: []const u8) anyerror!void {
try testing.expect(std.mem.containsAtLeast(u8, command, 1, "-t %0"));
}
}).check,
},
.{
.input = .{ .tmux = .{ .block_end = "" } },
// Moves on to pane_history for pane 1
.contains_command = "capture-pane",
.check_command = (struct {
fn check(_: *Viewer, command: []const u8) anyerror!void {
try testing.expect(std.mem.containsAtLeast(u8, command, 1, "-t %1"));
}
}).check,
},
.{
.input = .{ .tmux = .{ .block_end = "" } },
// Moves on to pane_visible for pane 1
.contains_command = "capture-pane",
.check_command = (struct {
fn check(_: *Viewer, command: []const u8) anyerror!void {