summaryrefslogtreecommitdiff
path: root/src/dump.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/dump.zig')
-rw-r--r--src/dump.zig34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 8e669b77..ef442ddb 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -99,6 +99,13 @@ pub const PaneKind = enum {
pub const Terminal = struct {
cwd: []const u8 = "",
+ /// The shell it runs when not the configured one (`Tty bash`); empty,
+ /// the configured one, as in dumps from before.
+ shell: []const u8 = "",
+ /// A command pane's line and how it ended (null: unknown, or still
+ /// running when dumped); empty for an interactive terminal.
+ command: []const u8 = "",
+ status: ?u8 = null,
/// The rendered scrollback and screen as plain text, one row per line.
stream: []const u8 = "",
stream_b64: []const u8 = "",
@@ -161,6 +168,9 @@ pub const Pane = struct {
rows: u16 = 0,
vweight: f32 = 1,
collapsed: bool = false,
+ /// Its serial when dumped (0 in older dumps): a Restore logs
+ /// `restored <old> <new>` for it.
+ serial: u32 = 0,
/// Exact editable tail when the user touched it. Null retains the live
/// default; a present empty slice deliberately restores an empty tail.
tag_tail: ?[]const u8 = null,
@@ -626,6 +636,7 @@ pub fn dumpState(p: *Pardes) !void {
else
try pardes.panes.Terminal.dumpPane(pane, arena, tag, body, scroll);
dp.tag_tail = pane.tag.own;
+ dp.serial = pane.serial;
dump_panes[panes_len] = dp;
panes_len += 1;
}
@@ -676,16 +687,22 @@ pub fn restore(p: *Pardes, zon_bytes: []const u8, from: []const u8) !*Pardes {
var opts = p.opts;
opts.cols = p.screen_w;
opts.rows = p.screen_h;
- const replacement = try initDump(p.gpa, opts, zon_bytes, p);
+ var old: [MAX_PANES]u32 = @splat(0);
+ const replacement = try initDump(p.gpa, opts, zon_bytes, p, &old);
pardes.ctlfs.events.notePath(replacement, "restore", from);
+ // Which serial each pane had, for a script that held the old ones.
+ for (replacement.panes, old) |slot, was| if (slot) |pane| if (was != 0) {
+ var rec: [32]u8 = undefined;
+ pardes.ctlfs.events.notePath(replacement, "restored", std.fmt.bufPrint(&rec, "{d} {d}", .{ was, pane.serial }) catch continue);
+ };
return replacement;
}
pub fn initFromDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8) !*Pardes {
- return initDump(gpa, opts, zon_bytes, null);
+ return initDump(gpa, opts, zon_bytes, null, null);
}
-fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previous: ?*const Pardes) !*Pardes {
+fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previous: ?*const Pardes, old_serials: ?*[MAX_PANES]u32) !*Pardes {
const image_gpa = opts.image_allocator orelse gpa;
const pdf_gpa = opts.pdf_allocator orelse gpa;
const tree_sitter_gpa = opts.tree_sitter_allocator orelse gpa;
@@ -735,17 +752,26 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
}
for (st.panes, 0..) |src, i| {
if (i >= MAX_PANES) break;
+ if (old_serials) |o| o[i] = src.serial;
const pane: *pardes.panes.Pane = switch (src.kind) {
.terminal => terminal: {
const t = src.terminal.?;
// A host that runs shells gets them back: the old history
// above a new shell in the directory it was in. The web
// shell and an isolated build only ever replay it.
+ // A command pane comes back finished, showing what it said
+ // and how it ended: its command is not run again.
const live = comptime (terminal_panes and platform != .web and !isolated);
- const revive = live and t.cwd.len <= effect_path_cap;
+ const revive = live and t.cwd.len <= effect_path_cap and t.command.len == 0;
const restored = try pardes.panes.Terminal.restore(p, src, revive);
p.installPane(i, restored);
try restored.setOwnedCwd(t.cwd);
+ if (t.shell.len > 0) restored.shell = try gpa.dupe(u8, t.shell);
+ if (t.command.len > 0) {
+ restored.command = try gpa.dupe(u8, t.command);
+ restored.command_done = true;
+ restored.command_status = t.status;
+ }
if (std.mem.startsWith(u8, src.tag, "TTY ")) restored.body.mode = .tty;
if (revive) p.emit(.{ .spawn = .{ .pane = @intCast(i), .serial = restored.serial, .cwd = .from(t.cwd) } });
break :terminal restored;