summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 12:29:21 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commitc5c1c200ad66a16b73428de2c369fc15aacac8b4 (patch)
treeeb569b17cce2e5faddcc740b994a2ad938d3b7cd /src/builtins.zig
parent21d2240b9b86ae5ba0036988b0ed84fbcf18d3af (diff)
downloadpardes-c5c1c200ad66a16b73428de2c369fc15aacac8b4.tar.gz
pardes-c5c1c200ad66a16b73428de2c369fc15aacac8b4.zip
An Exit or Restore refusal says the same word again discards the text
'<name>: Modified' read like a failure to retry, and a script that retried Exit or Restore threw the text away without knowing it. The refusal now names the word asking and what repeating it does, '<name>: Modified (Exit again to discard)', and the skill sets it apart from lock's 'file in use', which is the one to retry. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/builtins.zig')
-rw-r--r--src/builtins.zig17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 88c65704..6bfc9b26 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -220,7 +220,7 @@ test "Exit asks once about unsaved text, and quits when asked again" {
pane.file.?.saved_revision = pane.file.?.revision -% 1; // modified
try std.testing.expect(p.executeBuiltinLine(p.active, "Exit"));
try std.testing.expect(!p.quit);
- try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified"));
+ try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified (Exit again to discard)"));
// Told once, and nothing edited since: the second Exit quits.
try std.testing.expect(p.executeBuiltinLine(p.active, "Exit"));
try std.testing.expect(p.quit);
@@ -233,7 +233,7 @@ test "Restore asks about unsaved text as Exit does, and restores when asked agai
pane.file.?.saved_revision = pane.file.?.revision -% 1; // modified
try std.testing.expect(p.executeBuiltinLine(p.active, "Restore /tmp/some.dump.zon"));
try std.testing.expect(p.restore_req == null);
- try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified"));
+ try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified (Restore again to discard)"));
try std.testing.expect(p.executeBuiltinLine(p.active, "Restore /tmp/some.dump.zon"));
try std.testing.expectEqualStrings("/tmp/some.dump.zon", p.restore_req.?);
}
@@ -354,11 +354,13 @@ pub const Exec = struct {
/// acme's rowclean (editors/acme/wind.c:511-529, winclean), asked before
/// what would throw unsaved text away: each pane holding some nobody has
-/// been told about says so, `<name>: Modified`, and is then clean for the
+/// been told about says so, `<name>: Modified (Exit again to discard)`,
+/// naming the word asking, since repeating it throws the text away, and is
+/// then clean for the
/// asking, as winclean clears `dirty`; so the same word again, with
/// nothing edited since, goes ahead. A scratch of under 100 bytes is no
/// loss worth the question, as winclean does not ask for one.
-fn warnModified(c: Ctx) bool {
+fn warnModified(c: Ctx, asking: []const u8) bool {
var modified = false;
for (c.p.panes, 0..) |slot, id| {
const pane = slot orelse continue;
@@ -367,7 +369,8 @@ fn warnModified(c: Ctx) bool {
if (f.output != null and f.content.len < 100) continue;
if (pane.discard_warned == f.revision) continue;
pane.discard_warned = f.revision;
- c.p.reportError(id, f.path, error.Modified);
+ var buf: [limits.host_path_cap + 48]u8 = undefined;
+ c.p.reportFailure(id, std.fmt.bufPrint(&buf, "{s}: Modified ({s} again to discard)", .{ f.path, asking }) catch f.path);
modified = true;
}
return modified;
@@ -378,7 +381,7 @@ fn warnModified(c: Ctx) bool {
pub const Exit = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
- if (warnModified(c)) return;
+ if (warnModified(c, "Exit")) return;
c.p.quit = true;
c.p.emit(.quit);
}
@@ -433,7 +436,7 @@ pub const Restore = struct {
if (path.len > c.p.restore_buf.len) return;
// acme's Load adds a dump's windows to the ones there; a Restore
// replaces them all, so it asks what Exit asks first.
- if (warnModified(c)) return;
+ if (warnModified(c, "Restore")) return;
@memcpy(c.p.restore_buf[0..path.len], path);
c.p.restore_req = c.p.restore_buf[0..path.len];
}