summaryrefslogtreecommitdiff
path: root/src/dump.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/dump.zig')
-rw-r--r--src/dump.zig41
1 files changed, 40 insertions, 1 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 84321457..201f5bf2 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -232,6 +232,9 @@ pub const File = struct {
/// Its dot, q0 and q1 in bytes, as acme's dump keeps a window's; null
/// in older dumps.
dot: ?[2]u32 = null,
+ /// A Zerox twin: the index, in `panes`, of the earlier pane whose
+ /// buffer it shares, its text kept there once; null for none.
+ twin_of: ?u32 = null,
};
pub const ImagePalette = enum {
@@ -302,6 +305,8 @@ pub const State = struct {
/// config are kept on their own, and the font is the frontend's. Absent
/// in older dumps.
settings: []const []const u8 = &.{},
+ /// Incl's directories, in order; null in older dumps (the defaults).
+ incl: ?[]const []const u8 = null,
};
/// A header is a text like any other: it may hold newlines, but not a
@@ -765,6 +770,22 @@ pub fn dumpState(p: *Pardes) !void {
dump_panes[panes_len] = dp;
panes_len += 1;
}
+ // Zerox's twins: the text once, in the first; each other names it.
+ for (p.panes, 0..) |slot, id| {
+ const f = (slot orelse continue).file orelse continue;
+ if (f.twin == 0) continue;
+ const i = slot_to_pane[id] orelse continue;
+ for (p.panes[0..id], 0..) |earlier, j_id| {
+ const of = (earlier orelse continue).file orelse continue;
+ if (of.twin != f.twin) continue;
+ const j = slot_to_pane[j_id] orelse break;
+ if (dump_panes[i].file) |*df| {
+ df.twin_of = @intCast(j);
+ df.content_b64 = "";
+ }
+ break;
+ }
+ }
var columns: [MAX_COLS]Column = undefined;
var columns_len: usize = 0;
@@ -798,6 +819,7 @@ pub fn dumpState(p: *Pardes) !void {
.panes = dump_panes[0..panes_len],
.mounts = mounts[0..p.fs.mounts.items.len],
.settings = try changedSettings(p, arena),
+ .incl = p.incl.items,
};
try validate(state);
var out: std.Io.Writer.Allocating = .init(p.gpa);
@@ -842,6 +864,7 @@ fn applySettings(p: *Pardes, lines: []const []const u8) void {
}
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);
+ if (setting.action == .tab) config.tab_now = p.settings.tab;
}
}
@@ -902,6 +925,14 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
p.locations_config = st.locations_config;
p.settings.tree_context_tag_style = st.tree_context_tag_style;
applySettings(p, st.settings);
+ if (st.incl) |dirs| {
+ for (p.incl.items) |dir| p.gpa.free(dir);
+ p.incl.clearRetainingCapacity();
+ for (dirs) |dir| if (dir.len > 0 and dir[0] == '/' and std.mem.indexOfScalar(u8, dir, 0) == null) {
+ const copy = p.gpa.dupe(u8, dir) catch continue;
+ p.incl.append(p.gpa, copy) catch p.gpa.free(copy);
+ };
+ }
// A dump naming a ThemeFile asks the host to load it again: until it
// has, and for good if it fails, the theme this session showed goes on
// (a failed ThemeFile changes nothing, a Restore's included), unless
@@ -952,7 +983,12 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
if (t.petscii and pardes.panes.terminal.petscii(restored) == false) pardes.panes.terminal.togglePetscii(restored);
break :terminal restored;
},
- .file => try pardes.panes.File.restore(p, i, src),
+ .file => file: {
+ const restored = try pardes.panes.File.restore(p, i, src);
+ // A twin: on the earlier pane's buffer again.
+ if (src.file.?.twin_of) |j| if (j < i) pardes.panes.File.relink(p, j, i, src.file.?.dot);
+ break :file restored;
+ },
.image => restore_image: {
const im = src.image.?;
if (pardes.panes.Pdf.isPath(im.path)) {
@@ -1028,14 +1064,17 @@ test "a dump keeps the settings that differ from a fresh session's, and a restor
defer p.deinit();
try std.testing.expect(p.executeBuiltinLine(p.active, "Placement pardes"));
try std.testing.expect(p.executeBuiltinLine(p.active, "Verbose off"));
+ try std.testing.expect(p.executeBuiltinLine(p.active, "JumpScope all"));
try dumpState(p);
try std.testing.expect(std.mem.indexOf(u8, p.dump_out.?, "\"Placement pardes\"") != null);
+ try std.testing.expect(std.mem.indexOf(u8, p.dump_out.?, "\"JumpScope all\"") != 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);
+ try std.testing.expectEqual(config.Runtime.JumpScope.all, restored.settings.jump_scope);
}
test "a session with every column it may hold dumps and restores them all" {