diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 04:49:26 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 4e82c95653e1e8e03fde91e3cea2de04b3fabbc8 (patch) | |
| tree | 42c24f167214db291d4e3936ba61323eca8821b7 /src | |
| parent | 009e4ab8779bc7adc7b626814d36e62231d7a0ea (diff) | |
| download | pardes-4e82c95653e1e8e03fde91e3cea2de04b3fabbc8.tar.gz pardes-4e82c95653e1e8e03fde91e3cea2de04b3fabbc8.zip | |
Every refusal over unsaved text names a scratch by its pane too
Exit, Restore, Del and Delcol share one list (warnModifiedIn), but it was
built in 256 bytes, so with a few long paths a +New scratch near the end
fell off Exit's and Restore's, which list every pane; and several +New
panes were indistinguishable. The list is built in 1024 bytes (the
write's error is still cut to fit, between words), and a scratch is named
with its serial, /dir/+New (pane 12), the same everywhere.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.zig | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index 4490482d..3e35ca2f 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -463,7 +463,7 @@ fn warnModifiedIn(c: Ctx, asking: Pane.Discarding, which: Asked) bool { var modified = false; // Every pane asked about is named in the one refusal a ctl write gets, // as acme's rowclean names them all (wind.c:511). - var all_buf: [256]u8 = undefined; + var all_buf: [1024]u8 = undefined; var all = std.Io.Writer.fixed(&all_buf); for (c.p.panes, 0..) |slot, id| { const pane = slot orelse continue; @@ -486,9 +486,14 @@ fn warnModifiedIn(c: Ctx, asking: Pane.Discarding, which: Asked) bool { if (std.hash.Wyhash.hash(0, f.content) == saved) continue; if (pane.discard_warned) |w| if (w.revision == f.revision and w.by == asking) continue; pane.discard_warned = .{ .revision = f.revision, .by = asking }; - 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, @tagName(asking) }) catch f.path); - all.print("{s}{s}", .{ if (modified) ", " else "", f.path }) catch {}; + // Scratches share a name: each is named with its pane's serial too, + // `/dir/+New (pane 12)`, the same in every refusal (Exit, Restore, + // Del, Delcol). + var name_buf: [limits.host_path_cap + 24]u8 = undefined; + const name = if (scratch) std.fmt.bufPrint(&name_buf, "{s} (pane {d})", .{ f.path, pane.serial }) catch f.path else f.path; + var buf: [limits.host_path_cap + 72]u8 = undefined; + c.p.reportFailure(id, std.fmt.bufPrint(&buf, "{s}: Modified ({s} again to discard)", .{ name, @tagName(asking) }) catch name); + all.print("{s}{s}", .{ if (modified) ", " else "", name }) catch {}; modified = true; } if (modified and c.p.fs.no_prompt) { @@ -1806,7 +1811,12 @@ test "Exit and Restore name a modified +New scratch as well as files" { try std.testing.expect(!p.quit); const said = p.fs.failure[0..p.fs.failure_len]; try std.testing.expect(std.mem.indexOf(u8, said, "test.txt") != null); - try std.testing.expect(std.mem.indexOf(u8, said, config.scratch_buffer) != null); + var named: [64]u8 = undefined; + try std.testing.expect(std.mem.indexOf(u8, said, try std.fmt.bufPrint(&named, "{s} (pane {d})", .{ config.scratch_buffer, p.panes[p.active].?.serial })) != null); + // 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, p.fs.failure[0..p.fs.failure_len], named[0 .. config.scratch_buffer.len + 7]) != null); } test "Del and Delcol refuse a pane with unsaved text once, as acme's do, and close on the second" { |
