diff options
| author | Gabriel Schneider <[email protected]> | 2026-07-06 20:43:40 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-01 15:02:07 -0300 |
| commit | 513938c1cfb216a3bc4a3559cf7731b8e44a952f (patch) | |
| tree | 7b711c30ea6ebc255a1d691223b2cb93cd7dedf2 /src/tty.zig | |
| parent | d0ba070a87c54c538e5f788485391b0af927d0fb (diff) | |
| download | pardes-513938c1cfb216a3bc4a3559cf7731b8e44a952f.tar.gz pardes-513938c1cfb216a3bc4a3559cf7731b8e44a952f.zip | |
dumps: per-user data dir + timestamped names; Restore builtin loads a dump into the live session. dump.outPath resolves $PARDES_DUMP verbatim (the snapshot harness pins /tmp/pardes-dump.zon so dump/load/restore goldens stay deterministic), else $XDG_DATA_HOME|~/.local/share /pardes/pardes-YYYYMMDD-HHMMSS.zon (dir mkdir-ed; wall clock via libc clock_gettime — std.time.timestamp is gone in 0.16). After write_dump the shell reports the written path back (core.setLastDump) and the topbar grows "Restore <path>": middle-clicking Restore reloads the last dump, and "Restore <path>" executed anywhere takes the path as its first argument (onSelect prefix match). Core stays sans-IO: the builtin stashes restore_req; each shell consumes takeRestore() after drainEffects and swaps in initFromDump at the current screen size (pre-sized: dump panes never greet), tearing down the live ptys (tty: cancel reader + close + gen bump; gui: SIGKILL, the gen-guarded eof closes the old fds). Web ignores it. New restore.snap golden: KEEPME survives the restore, GONESOON echoed after Dump does not, the topbar word appears then resets. 29/29.
Diffstat (limited to 'src/tty.zig')
| -rw-r--r-- | src/tty.zig | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/src/tty.zig b/src/tty.zig index 97f10a7a..c62ace3d 100644 --- a/src/tty.zig +++ b/src/tty.zig @@ -68,7 +68,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { pardes.image.start(io, gpa); defer pardes.image.stop(); - const core = if (opts.load_path) |lp| blk: { + var core = if (opts.load_path) |lp| blk: { const bytes = try look.readFile(gpa, lp); defer gpa.free(bytes); break :blk try pardes.Pardes.initFromDump(gpa, opts, bytes); @@ -193,6 +193,27 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { drainEffects(core, &ptys, &gens, io, gpa, &loop, &vx, &tty, true); if (core.quit) break; + // Restore builtin: swap in a core rebuilt from the dump; the live + // shells die with their masters (readers canceled, gens bumped so + // their late eofs never touch the replay panes) + if (core.takeRestore()) |rp| blk: { + const bytes = look.readFile(gpa, rp) catch break :blk; + defer gpa.free(bytes); + var o = core.opts; + o.cols = core.screen_w; + o.rows = core.screen_h; // pre-size: dump panes never greet + const nc = pardes.Pardes.initFromDump(gpa, o, bytes) catch break :blk; + for (&ptys, 0..) |*slot, pid| if (slot.*) |*pt| { + pt.reader.cancel(io) catch {}; + _ = libc.close(pt.file.handle); + slot.* = null; + gens[pid] +%= 1; + }; + kitty_handles = @splat(null); + core.deinit(); + core = nc; + } + // live cwd for tags/look: cheap per-pane lookup, per frame for (&ptys, 0..) |*slot, id| if (slot.*) |pt| { var lbuf: [1024]u8 = undefined; @@ -310,10 +331,13 @@ fn drainEffects( }, .write_dump => { const out = core.dump_out orelse continue; - const fd = libc.open(pardes.dump.default_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + var pbuf: [1024:0]u8 = undefined; + const path = pardes.dump.outPath(&pbuf) orelse continue; + const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); if (fd < 0) continue; writeFd(fd, out); _ = libc.close(fd); + core.setLastDump(path); }, .set_clipboard => { // mirror the core's yank register out via OSC 52 |
