summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 16:42:18 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:16 -0300
commita59e1ebfdd9f59102de98549eacddd7ca5d3ee84 (patch)
tree36e1cd463488f656bfe4d642ac12d7dbd6ccbf12 /src
parent9680a860f8a8309f8b9d82067f145561b6b57f49 (diff)
downloadpardes-a59e1ebfdd9f59102de98549eacddd7ca5d3ee84.tar.gz
pardes-a59e1ebfdd9f59102de98549eacddd7ca5d3ee84.zip
A refused Delcol changes nothing: no +Unsaved opens, no focus moves
Delcol's refusal opened +Unsaved, placing a pane in the layout it was refusing to change. Its unsaved records and notice say which panes; the list pane is left to the refusals of the other words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/builtins.zig9
-rw-r--r--src/ninep/ctl.zig23
2 files changed, 29 insertions, 3 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 4a0b107c..e47afeb4 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -562,7 +562,9 @@ fn warnModifiedIn(c: Ctx, asking: Pane.Discarding, which: Asked) bool {
}
if (count > 0) {
listed.print(arena, "\n{s} again to discard\n", .{@tagName(asking)}) catch {};
- if (c.p.gpa.dupe(u8, listed.items)) |content| panes.Output.openUnsaved(c.p, c.id, content) else |_| {}
+ // A refused Delcol changes nothing, the layout included: its records
+ // and its notice say it, and no +Unsaved opens.
+ if (asking != .Delcol) if (c.p.gpa.dupe(u8, listed.items)) |content| panes.Output.openUnsaved(c.p, c.id, content) else |_| {};
var short: [96]u8 = undefined;
c.p.reportFailure(c.id, std.fmt.bufPrint(&short, "{d} unsaved pane{s} \u{2014} {s} again to discard", .{ count, if (count == 1) "" else "s", @tagName(asking) }) catch "unsaved panes");
}
@@ -2003,7 +2005,7 @@ test "Exit and Restore name a modified +New scratch as well as files" {
// Delcol, Restore and Exit name it the same way.
p.fs.failure_len = 0;
try std.testing.expect(p.executeBuiltinLine(p.active, "Delcol"));
- try std.testing.expect(std.mem.indexOf(u8, unsavedList(p), "Delcol again to discard") != null);
+ try std.testing.expect(std.mem.indexOf(u8, unsavedList(p), "Delcol again to discard") == null);
try std.testing.expect(std.mem.indexOf(u8, unsavedList(p), named[0 .. config.scratch_buffer.len + 7]) != null);
}
@@ -2016,7 +2018,8 @@ test "Del and Delcol refuse a pane with unsaved text once, as acme's do, and clo
const serial = pane.serial;
try std.testing.expect(p.executeBuiltinLine(p.active, "Delcol"));
try std.testing.expect(p.paneBySerial(serial) != null);
- try std.testing.expect(std.mem.endsWith(u8, unsavedList(p), ": Modified\n\nDelcol again to discard\n"));
+ // A refused Delcol changes nothing: no +Unsaved (its records say it).
+ try std.testing.expect(std.mem.indexOf(u8, unsavedList(p), "Delcol") == null);
// Each word is warned on its own: Del asks too, then closes.
try std.testing.expect(p.executeBuiltinLine(p.active, "Del"));
try std.testing.expect(p.paneBySerial(serial) != null);
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 7986333c..1ac53bb7 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -3048,3 +3048,26 @@ test "a bad command inside an Edit block written whole is named, not the } after
try testing.expect(std.mem.indexOf(u8, r.reply.ename, "z") != null);
try testing.expectEqualStrings("abc\n", p.panes[0].?.file.?.content);
}
+
+test "a refused Delcol changes nothing: no pane, no focus" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ _ = wr(p, @intFromEnum(tree.TopFile.ctl), "Newcol\n");
+ const made = try th.newPane(p);
+ _ = wr(p, Node.of(made, .name), "/tmp/pardes-delcol-refused.txt\n");
+ _ = wr(p, Node.of(made, .body), "edit\n");
+ p.sync();
+ const col = layout.findPane(p, p.paneBySerial(made).?).?.col;
+ const active = p.active;
+ const active_column = p.active_column;
+ var count: usize = 0;
+ for (p.panes) |slot| count += @intFromBool(slot != null);
+ try testing.expectEqual(Status.err, wr(p, Node.ofCol(layout.columnSerial(p, col), .ctl), "Delcol\n").reply.status);
+ p.sync();
+ var after: usize = 0;
+ for (p.panes) |slot| after += @intFromBool(slot != null);
+ try testing.expectEqual(count, after);
+ try testing.expectEqual(active, p.active);
+ try testing.expectEqual(active_column, p.active_column);
+ try testing.expect(th.logHas(p, "unsaved "));
+}