From 07a3f53993a27c886ccb3ed665acb9c8b34a2873 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 16:12:29 -0300 Subject: A tag's edited text stays alive until the next edit, so ms and md in a tag read it whole setEditText freed the text a tag edit was handed once it had copied the tag's own part out of it, but every caller reads that text back to place the cursor, and surround goes on to edit it again: ms and md in a tag read freed memory. The same held for a terminal without an edit buffer and a text with no pane. The text is now kept until the next such edit (edit.retireEditText), which covers every caller at once; the callers the audit found reading it back are surround's two, the paste and replace paths, the number adjust, and the insert-mode Enter. Co-Authored-By: Claude Opus 5.5 --- test/panes.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test') diff --git a/test/panes.zig b/test/panes.zig index 4e98f449..0b9909ad 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -314,6 +314,19 @@ const TagNavigationTests = struct { try std.testing.expect(pane.prompt == .none and pane.focus == .body); } + test "ms and md edit a tag's own text, and the text the edit made is read back whole" { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 20 }); + defer p.deinit(); + const pane = try p.setTestFile("body\n"); + p.update(.tick); + key(p, ':'); // the tag, on `Save` the first time + for ("miwms(") |cp| key(p, cp); + try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), "(Save)") != null); + for ("md(") |cp| key(p, cp); + try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), " Save ") != null); + try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), "(") == null); + } + test "the keyboard reaches a tag's path, which it can select and yank but not edit" { const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 20 }); defer p.deinit(); -- cgit v1.3