summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dump.zig3
-rw-r--r--src/pardes.zig38
2 files changed, 39 insertions, 2 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 4db3df24..0e911ec1 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -753,6 +753,7 @@ pub fn restore(p: *Pardes, zon_bytes: []const u8, from: []const u8) !*Pardes {
opts.rows = p.screen_h;
var old: OldSerials = .{};
const replacement = try initDump(p.gpa, opts, zon_bytes, p, &old);
+ replacement.pointRestoreAt(from);
pardes.ctlfs.events.notePath(replacement, "restore", from);
// Which serial each pane and column had, for a script that held them.
for (replacement.panes, old.panes) |slot, was| if (slot) |pane| if (was != 0) {
@@ -802,6 +803,8 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
p.cell_pixels = old.cell_pixels;
p.row_metrics = old.row_metrics;
p.native_images = old.native_images;
+ // The workspace tag's Restore word names the dump it came from.
+ if (old.last_dump) |d| p.last_dump = try gpa.dupe(u8, d);
// Recent goes on across a Restore, the old session's own list.
p.recent = old.recent.clone(p.recentGpa());
p.recent_loaded = old.recent_loaded;
diff --git a/src/pardes.zig b/src/pardes.zig
index 4147032b..c405c3d9 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -3247,6 +3247,21 @@ test "tabbed file aligns syntax cursor and mouse at the nearest insertion gap" {
try std.testing.expect(look.expandedSel(p, pane, .{ .state = .dragging, .c0 = separator, .c1 = separator, .r0 = BOX_H, .r1 = BOX_H }) == null);
}
+test "the workspace tag's Restore word names the last dump, the tag edited around it or not, across a Restore too" {
+ const p = try Pardes.init(std.testing.allocator, .{ .cols = 100, .rows = 20, .tty_only = true });
+ defer p.deinit();
+ p.setLastDump("/tmp/a.zon");
+ // The tag edited: its own text holds the Restore word as it was then.
+ p.global_tag.own = try p.gpa.dupe(u8, try std.fmt.allocPrint(p.scratch.allocator(), "{s} Mine", .{tagline.headerDefault(p, .workspace)}));
+ p.setLastDump("/tmp/b.zon");
+ try std.testing.expect(std.mem.indexOf(u8, p.global_tag.own.?, "Restore /tmp/b.zon Mine") != null);
+ try dump.dumpState(p);
+ const restored = try dump.restore(p, p.dump_out.?, "/tmp/c.zon");
+ defer restored.deinit();
+ try std.testing.expect(std.mem.indexOf(u8, restored.global_tag.own.?, "Restore /tmp/c.zon Mine") != null);
+ try std.testing.expectEqualStrings("/tmp/c.zon", restored.last_dump.?);
+}
+
test "editable workspace and column tags are typed into and persist" {
const p = try Pardes.init(std.testing.allocator, .{ .cols = 100, .rows = 20, .tty_only = true });
defer p.deinit();
@@ -4797,10 +4812,29 @@ pub const Pardes = struct {
/// shell feedback after write_dump: remember where the dump landed (the
/// topbar grows a `Restore <path>` word pointing at it)
pub fn setLastDump(p: *Pardes, path: []const u8) void {
+ p.pointRestoreAt(path);
+ ctlfs.events.notePath(p, "dump", path);
+ }
+
+ /// The workspace tag's `Restore <path>` names `path` from now on: the
+ /// default's does by itself, and one the tag was edited around (its own
+ /// text) has the old path swapped, never left pointing at a dump that is
+ /// not the last.
+ pub fn pointRestoreAt(p: *Pardes, path: []const u8) void {
const copy = p.gpa.dupe(u8, path) catch return;
- if (p.last_dump) |old| p.gpa.free(old);
+ if (p.last_dump) |old| {
+ if (p.global_tag.own) |own| swap: {
+ const a = p.scratch.allocator();
+ const was = std.fmt.allocPrint(a, "Restore {s}", .{old}) catch break :swap;
+ if (std.mem.indexOf(u8, own, was) == null) break :swap;
+ const now = std.fmt.allocPrint(a, "Restore {s}", .{path}) catch break :swap;
+ const swapped = std.mem.replaceOwned(u8, p.gpa, own, was, now) catch break :swap;
+ p.gpa.free(own);
+ p.global_tag.own = swapped;
+ }
+ p.gpa.free(old);
+ }
p.last_dump = copy;
- ctlfs.events.notePath(p, "dump", path);
}
/// the shell polls this each frame: a pending Restore's dump path, or null