summaryrefslogtreecommitdiff
path: root/src/ninep/ctl.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep/ctl.zig')
-rw-r--r--src/ninep/ctl.zig54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 6631e5f9..22a0923b 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -2106,6 +2106,60 @@ test "a column takes panes until their documented minimums fill it, not until no
}
}
+test "a closed file is found again: Recent and /recent list it closed, a look at its row reopens it at its dot, and a jump back does too" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ var tmp = testing.tmpDir(.{});
+ defer tmp.cleanup();
+ try tmp.dir.writeFile(testing.io, .{ .sub_path = "a.txt", .data = "one\ntwo\nthree\n" });
+ try tmp.dir.writeFile(testing.io, .{ .sub_path = "b.txt", .data = "bee\n" });
+ var dir_buf: [4096]u8 = undefined;
+ const dir = dir_buf[0..try tmp.dir.realPath(testing.io, &dir_buf)];
+ var line: [4200]u8 = undefined;
+ const a_path = try std.fmt.bufPrint(&line, "{s}/a.txt", .{dir});
+ var a_buf: [4200]u8 = undefined;
+ const a = a_buf[0..a_path.len];
+ @memcpy(a, a_path);
+ // Opened, its dot on line 3, then closed.
+ try testing.expectEqual(Status.ok, wr(p, root_look, try std.fmt.bufPrint(&line, "{s}:3\n", .{a})).reply.status);
+ p.sync();
+ const opened = p.active;
+ try testing.expectEqualStrings(a, p.panes[opened].?.file.?.path);
+ var want: [4300]u8 = undefined;
+ try testing.expect(std.mem.indexOf(u8, rd(p, @intFromEnum(tree.TopFile.recent), 0, 8192).bytes, try std.fmt.bufPrint(&want, "open {s}\n", .{a})) != null);
+ // Another file, so the jumplist has somewhere to come back from.
+ try testing.expectEqual(Status.ok, wr(p, root_look, try std.fmt.bufPrint(&line, "{s}/b.txt\n", .{dir})).reply.status);
+ p.sync();
+ try testing.expectEqual(Status.ok, wr(p, Node.of(p.panes[opened].?.serial, .ctl), "Del\n").reply.status);
+ p.sync();
+ try testing.expect(std.mem.indexOf(u8, rd(p, @intFromEnum(tree.TopFile.recent), 0, 8192).bytes, try std.fmt.bufPrint(&want, "closed {s}\n", .{a})) != null);
+ // Recent lists it, closed, at its dot; a look at the row opens it there.
+ try testing.expectEqual(Status.ok, wr(p, root_exec, "Recent\n").reply.status);
+ const rows = p.panes[p.paneBySerial(try std.fmt.parseInt(u32, std.mem.trimEnd(u8, rd(p, root_exec, 0, 64).bytes, "\n"), 10)).?].?;
+ const at = std.mem.indexOf(u8, rows.file.?.content, try std.fmt.bufPrint(&want, "{s}:3:", .{a})).?;
+ const row = rows.file.?.content[at .. std.mem.indexOfScalarPos(u8, rows.file.?.content, at, '\n').?];
+ try testing.expect(std.mem.endsWith(u8, row, " closed"));
+ try testing.expectEqual(Status.ok, wr(p, Node.of(rows.serial, .look), try std.fmt.bufPrint(&line, "{s}\n", .{row[0 .. row.len - " closed".len]})).reply.status);
+ p.sync();
+ const back = p.panes[p.active].?;
+ try testing.expectEqualStrings(a, back.file.?.path);
+ try testing.expectEqual(@as(i32, 2), back.body.cur_row);
+ // Closed again; the jumplist keeps its entry, closed, and a jump back
+ // to it opens it again.
+ _ = wr(p, Node.of(back.serial, .ctl), "Del\n");
+ p.sync();
+ var closed_entry = false;
+ for (p.jumps[0..p.njumps]) |j| closed_entry = closed_entry or j.serial == 0;
+ try testing.expect(closed_entry);
+ var tries: usize = 0;
+ while (tries < p.njumps) : (tries += 1) {
+ p.jumpBy(-1);
+ p.sync();
+ if (p.panes[p.active].?.file) |f| if (std.mem.eql(u8, f.path, a)) break;
+ }
+ try testing.expectEqualStrings(a, p.panes[p.active].?.file.?.path);
+}
+
test "size is monotonic: growing is never refused, and a size once taken is taken again" {
const p = try Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 160, .rows = 60 });
defer p.deinit();