summaryrefslogtreecommitdiff
path: root/src/dump.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 23:48:17 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commita6c4ab97de9f9624d4d4d37a4f63cae342e314fb (patch)
tree0dc35fd6821344602556ef94cfdaf174ba9911e5 /src/dump.zig
parentc284475c8681ad57c32497c7948e0b020281f4ed (diff)
downloadpardes-a6c4ab97de9f9624d4d4d37a4f63cae342e314fb.tar.gz
pardes-a6c4ab97de9f9624d4d4d37a4f63cae342e314fb.zip
A dump keeps the settings changed from a fresh session's, and Restore sets them
A session running with Placement pardes came back from Restore as acme: a dump kept the layout and the theme but no setting. It now keeps every setting line that differs from a fresh session's, as the root ctl reads it, and a Restore applies them; the theme stays where it was kept, the font the frontend's, and REPL bindings are still dropped. The dump golden gains the three the snapshot harness sets. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/dump.zig')
-rw-r--r--src/dump.zig54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 5ebb3c8d..77e2c2ba 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -200,6 +200,11 @@ pub const State = struct {
columns: []const Column = &.{},
panes: []const Pane = &.{},
mounts: []const Mount = &.{},
+ /// The settings that differ from a fresh session's, each a line as the
+ /// root ctl takes it (`Placement pardes`); the theme and the locations
+ /// config are kept on their own, and the font is the frontend's. Absent
+ /// in older dumps.
+ settings: []const []const u8 = &.{},
};
/// A header is a text like any other: it may hold newlines, but not a
@@ -680,6 +685,7 @@ pub fn dumpState(p: *Pardes) !void {
.columns = columns[0..columns_len],
.panes = dump_panes[0..panes_len],
.mounts = mounts[0..p.fs.mounts.items.len],
+ .settings = try changedSettings(p, arena),
};
try validate(state);
var out: std.Io.Writer.Allocating = .init(p.gpa);
@@ -690,6 +696,37 @@ pub fn dumpState(p: *Pardes) !void {
p.emit(.write_dump);
}
+/// The setting lines that differ from a fresh session's, as the root ctl
+/// reads them, less the ones a dump keeps apart.
+fn changedSettings(p: *Pardes, arena: std.mem.Allocator) ![]const []const u8 {
+ var now: std.Io.Writer.Allocating = .init(arena);
+ var fresh: std.Io.Writer.Allocating = .init(arena);
+ const defaults: config.Runtime = .{};
+ try pardes.ctlfs.ctl.writeSettingsOf(p, &p.settings, &now.writer);
+ try pardes.ctlfs.ctl.writeSettingsOf(p, &defaults, &fresh.writer);
+ var out: std.ArrayList([]const u8) = .empty;
+ var lines = std.mem.splitScalar(u8, now.written(), '\n');
+ while (lines.next()) |line| {
+ if (line.len == 0) continue;
+ const word = line[0 .. std.mem.indexOfScalar(u8, line, ' ') orelse line.len];
+ if (std.mem.eql(u8, word, "Theme") or std.mem.eql(u8, word, "Font")) continue;
+ var same = std.mem.splitScalar(u8, fresh.written(), '\n');
+ while (same.next()) |other| {
+ if (std.mem.eql(u8, other, line)) break;
+ } else try out.append(arena, line);
+ }
+ return out.items;
+}
+
+/// Applies a dump's setting lines, each as the root ctl would.
+fn applySettings(p: *Pardes, lines: []const []const u8) void {
+ for (lines) |line| {
+ const sp = std.mem.indexOfScalar(u8, line, ' ');
+ const setting = config.Runtime.find(line[0 .. sp orelse line.len]) orelse continue;
+ _ = p.settings.apply(setting, if (sp) |s| line[s + 1 ..] else null);
+ }
+}
+
/// The replacement core for a Restore of the dump at `from`, whose log says
/// so after its panes' `new`s, for a client that reconnects to read.
pub fn restore(p: *Pardes, zon_bytes: []const u8, from: []const u8) !*Pardes {
@@ -745,6 +782,7 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
const st = parsed.value;
p.locations_config = st.locations_config;
p.settings.tree_context_tag_style = st.tree_context_tag_style;
+ applySettings(p, st.settings);
for (st.mounts) |mount| {
var already_mounted = false;
for (p.fs.mounts.items) |existing| {
@@ -849,3 +887,19 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
ctlfs.events.announce(p);
return p;
}
+
+test "a dump keeps the settings that differ from a fresh session's, and a restore applies them" {
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true });
+ defer p.deinit();
+ try std.testing.expect(p.executeBuiltinLine(p.active, "Placement pardes"));
+ try std.testing.expect(p.executeBuiltinLine(p.active, "Verbose off"));
+ try dumpState(p);
+ try std.testing.expect(std.mem.indexOf(u8, p.dump_out.?, "\"Placement pardes\"") != null);
+ // What is left at its default is not written.
+ try std.testing.expect(std.mem.indexOf(u8, p.dump_out.?, "\"BootShell keep\"") == null);
+ const restored = try initFromDump(gpa, .{ .tty_only = true }, p.dump_out.?);
+ defer restored.deinit();
+ try std.testing.expectEqual(config.Runtime.Placement.pardes, restored.settings.placement);
+ try std.testing.expect(!restored.settings.verbose);
+}