diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 18:04:25 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:17 -0300 |
| commit | f65cb652243bf0a63eecdd4d6c5cd8ccbc3fd2ea (patch) | |
| tree | 28f31651e214eaf4177209122e263fefaf186328 | |
| parent | b608fc54c40ff3dff6057569bd65d3f729c6d4f9 (diff) | |
| download | pardes-f65cb652243bf0a63eecdd4d6c5cd8ccbc3fd2ea.tar.gz pardes-f65cb652243bf0a63eecdd4d6c5cd8ccbc3fd2ea.zip | |
Under pardes's placement a pane whose neighbour is in no column goes at a column's foot, not nowhere
After Delcol took the last column's panes, pane/new under Placement made a scratch that no column held, since a scratch was placed only under the asking pane, which was gone; a look from it then unwrapped the missing parent in belowParent and panicked (the 9P monkey's crash-e1873f34). Both now fall back to the foot of the active column, else the last.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | src/exec.zig | 13 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 20 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/exec.zig b/src/exec.zig index 87f6da40..2c42389c 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -1150,7 +1150,7 @@ fn pardesPlace(p: *Pardes, from: usize, id: usize, kind: NewPane) void { .scratch, .fs => if (layout.findPane(p, from)) |sf| { layout.insert(p, sf.col, sf.idx + 1, id); layout.splitBelow(p, from, nt); - }, + } else atFoot(p, id), .shell => belowParent(p, from, id), .doc, .errors => pardesDoc(p, from, id), .command => { @@ -1160,9 +1160,18 @@ fn pardesPlace(p: *Pardes, from: usize, id: usize, kind: NewPane) void { } } +/// Where a pane goes when the one it would go under is in no column (Delcol +/// took them all, or it was never placed): the foot of the active column, +/// else of the last. +fn atFoot(p: *Pardes, id: usize) void { + const c = p.activeColumn() orelse p.ncol - 1; + layout.insert(p, c, p.col_n[c], id); + if (p.col_n[c] == 1) p.panes[id].?.vweight = 1; +} + fn belowParent(p: *Pardes, from: usize, id: usize) void { const parent = layout.splitParent(p, from); - const f = layout.findPane(p, parent).?; + const f = layout.findPane(p, parent) orelse return atFoot(p, id); layout.insert(p, f.col, f.idx + 1, id); layout.splitBelow(p, parent, p.panes[id].?); } diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index b9268208..59a80f36 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1752,6 +1752,26 @@ test "a look after Newcol fills the empty column the keyboard is on" { try testing.expectEqual(p.active, p.col_panes[p.ncol - 1][0]); } +test "a look under pardes's placement, from a pane pane/new made after Delcol, opens its file" { + const gpa = testing.allocator; + const p = try withFile(gpa, "x\n"); + defer p.deinit(); + var tmp = testing.tmpDir(.{}); + defer tmp.cleanup(); + try tmp.dir.writeFile(testing.io, .{ .sub_path = "f.txt", .data = "file\n" }); + var dir: [4096]u8 = undefined; + const at = dir[0..try tmp.dir.realPath(testing.io, &dir)]; + var line: [4200]u8 = undefined; + const first = serialOf(p); + try testing.expectEqual(tree.Status.ok, wr(p, Node.of(first, .exec), "Placement\n").reply.status); + try testing.expectEqual(tree.Status.ok, wr(p, Node.of(first, .exec), "Delcol\n").reply.status); + const made = try th.newPane(p); + try testing.expectEqual(tree.Status.ok, wr(p, Node.of(made, .look), try std.fmt.bufPrint(&line, "{s}/f.txt:#4\n", .{at})).reply.status); + // The pane pane/new made is placed, and so is the one its look opened. + for (p.panes, 0..) |slot, i| if (slot != null) try testing.expect(layout.findPane(p, i) != null); + try testing.expect(p.panes[p.active].?.serial != made); +} + test "a Restore of a file that is no dump fails the write before any warning, and a failed Dump fails its write" { if (comptime !pardes.hosted) return error.SkipZigTest; const p = try withFile(testing.allocator, "x\n"); |
