From 3bddd662eac9a7829174f3c54b498bda84df1961 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 1 Oct 2026 02:40:12 -0300 Subject: A Restore, or -l, of a dump naming a ThemeFile asks the host to load it again, as a /ctl write of it does The dump's ThemeFile line went to the settings table, which has no such setting and never asks the host to read a file, so a restored session came back in the default theme. The restore now makes the request a /ctl ThemeFile makes, and the host loads the file. Co-Authored-By: Claude Opus 5.5 --- src/dump.zig | 6 ++++++ src/ninep/ctl.zig | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/dump.zig b/src/dump.zig index 983d5894..f8b99ef4 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -811,6 +811,12 @@ fn changedSettings(p: *Pardes, arena: std.mem.Allocator) ![]const []const u8 { fn applySettings(p: *Pardes, lines: []const []const u8) void { for (lines) |line| { const sp = std.mem.indexOfScalar(u8, line, ' '); + // A ThemeFile is a request the host answers by reading the file, as + // a /ctl write of it is: asked again here, not dropped. + if (std.mem.eql(u8, line[0 .. sp orelse line.len], "ThemeFile")) { + if (sp) |s| colors.requestThemeFile(p, 0, line[s + 1 ..]); + continue; + } 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); } diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index e963da3f..6326b1c0 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -2034,6 +2034,29 @@ test "DumpConfig's whole report writes back to the root ctl, line by line, with } } +test "a Restore asks again for the ThemeFile the dump names, as a /ctl write of it does" { + if (comptime !pardes.hosted) return; + const gpa = testing.allocator; + const p = try withFile(gpa, "x\n"); + defer p.deinit(); + const good = "/tmp/pardes-restored-theme.zon"; + _ = wr(p, @intFromEnum(tree.TopFile.ctl), "ThemeFile " ++ good ++ "\n"); + var custom = pardes.themes[0]; + custom.name = "restored"; + var encoded: std.Io.Writer.Allocating = .init(gpa); + defer encoded.deinit(); + try std.zon.stringify.serialize(custom, .{}, &encoded.writer); + try testing.expect(pardes.colors.loadThemeFile(p, p.theme_file_generation, encoded.written(), false)); + try pardes.dump.dumpState(p); + const restored = try pardes.dump.restore(p, p.dump_out.?, "/tmp/pardes.dump.zon"); + defer restored.deinit(); + const asked = while (restored.nextEffect()) |effect| switch (effect) { + .theme_file => |t| if (t.on) break t, + else => {}, + } else return error.NoThemeFileAsked; + try testing.expectEqualStrings(good, pardes.colors.themeFileRequest(restored, asked.generation).?.path); +} + test "a ThemeFile that fails to load changes nothing: the root ctl still names the one loaded, or none" { if (comptime !pardes.hosted) return; const gpa = testing.allocator; -- cgit v1.3