diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 23:48:17 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | a6c4ab97de9f9624d4d4d37a4f63cae342e314fb (patch) | |
| tree | 0dc35fd6821344602556ef94cfdaf174ba9911e5 /src/dump.zig | |
| parent | c284475c8681ad57c32497c7948e0b020281f4ed (diff) | |
| download | pardes-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.zig | 54 |
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); +} |
