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.zig56
1 files changed, 55 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 188795de..537ac4d0 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -1829,6 +1829,60 @@ test "Putall saves every pane with unsaved edits to a file, one each, and leaves
try testing.expectEqual(@as(usize, 1), saves);
}
+test "Zerox makes a second pane on one buffer: one text, undo and dirty state, its own cursor; Save cleans both, Del of one asks nothing" {
+ var tmp = testing.tmpDir(.{});
+ defer tmp.cleanup();
+ var dir_buf: [4096]u8 = undefined;
+ const dir = dir_buf[0..try tmp.dir.realPath(testing.io, &dir_buf)];
+ const p = try withFile(testing.allocator, "one\ntwo\nthree\n");
+ defer p.deinit();
+ const first = serialOf(p);
+ var name: [std.fs.max_path_bytes + 8]u8 = undefined;
+ _ = wr(p, Node.of(first, .name), try std.fmt.bufPrint(&name, "{s}/z.txt\n", .{dir}));
+ try testing.expect(p.executeBuiltinLine(0, "Zerox"));
+ const twin_id = for (p.panes, 0..) |slot, id| {
+ if (id != 0) if (slot) |pane| if (pane.file != null) break id;
+ } else return error.NoTwin;
+ const a = p.panes[0].?;
+ const b = p.panes[twin_id].?;
+ // Both in the index, each its serial, one name.
+ const index = rd(p, @intFromEnum(tree.TopFile.index), 0, 4096).bytes;
+ try testing.expectEqual(@as(usize, 2), std.mem.count(u8, index, "/z.txt"));
+ // b's cursor on `three`; a line written above it in a moves it down.
+ b.body.cur_row = 2;
+ b.body.cur_col = 1;
+ _ = wr(p, Node.of(first, .addr), "0");
+ try testing.expectEqual(Status.ok, wr(p, Node.of(first, .data), "zero\n").reply.status);
+ try testing.expectEqualStrings("zero\none\ntwo\nthree\n", b.file.?.content);
+ try testing.expectEqual(a.file.?.content.ptr, b.file.?.content.ptr);
+ try testing.expectEqual(@as(i32, 3), b.body.cur_row);
+ try testing.expectEqual(@as(i32, 1), b.body.cur_col);
+ try testing.expect(pane_files.dirtyOf(a) and pane_files.dirtyOf(b));
+ // A write through b is a's too; Undo in a takes it back from both.
+ try testing.expectEqual(Status.ok, wr(p, Node.of(b.serial, .body), "four\n").reply.status);
+ try testing.expectEqualStrings("zero\none\ntwo\nthree\nfour\n", a.file.?.content);
+ try testing.expect(p.executeBuiltinLine(0, "Undo"));
+ try testing.expectEqualStrings("zero\none\ntwo\nthree\n", b.file.?.content);
+ // Saved from b: both come clean.
+ try testing.expect(p.executeBuiltinLine(twin_id, "Save"));
+ while (p.nextEffect()) |e| p.perform(e);
+ try testing.expect(!pane_files.dirtyOf(a) and !pane_files.dirtyOf(b));
+ try testing.expectEqualStrings("zero\none\ntwo\nthree\n", p.fallback.get(b.file.?.path).?);
+ // Edited again, Del of a asks nothing: b holds the text.
+ try testing.expectEqual(Status.ok, wr(p, Node.of(b.serial, .body), "five\n").reply.status);
+ const failures = p.fs.failures;
+ try testing.expect(p.executeBuiltinLine(0, "Del"));
+ p.sync();
+ try testing.expectEqual(failures, p.fs.failures);
+ try testing.expect(p.paneBySerial(first) == null);
+ try testing.expect(pane_files.dirtyOf(b));
+ try testing.expectEqualStrings("zero\none\ntwo\nthree\nfive\n", b.file.?.content);
+ // Alone now, it is no twin; Del asks about it as about any pane.
+ try testing.expectEqual(@as(u32, 0), b.file.?.twin);
+ try testing.expect(p.executeBuiltinLine(p.paneBySerial(b.serial).?, "Del"));
+ try testing.expect(p.fs.failures != failures);
+}
+
test "a body write to a terminal is typed input, not a paste, even to a program that asked for bracketed paste" {
const p = try Pardes.init(testing.allocator, .{ .cols = 90, .rows = 30 });
defer p.deinit();
@@ -3211,7 +3265,7 @@ test "acme's words run as pardes's (Put is Save, Delete a Del that does not ask)
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();
const serial = serialOf(p);
- for ([_][]const u8{ "Snarf\n", "Zerox\n", "Indent\n", "Local\n", "Abort\n" }) |line| {
+ for ([_][]const u8{ "Snarf\n", "Indent\n", "Local\n", "Abort\n" }) |line| {
for ([_]u64{ Node.of(serial, .ctl), Node.of(serial, .exec) }) |node| {
const r = wr(p, node, line);
try testing.expectEqual(E.INVAL, r.errno());