mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-11 03:39:36 +00:00
terminal/search: drop pruned selections
Partial history erasure can remove a page without marking tracked pins as garbage because they move coherently to the next page. ScreenSearch therefore retained a selection whose cached history result was subsequently removed by pruneHistory. Selecting again indexed an empty history result list and panicked. Clear the tracked selection when its combined result index falls within the history suffix being pruned. Retained active and newer history selections keep their existing indices.
This commit is contained in:
@@ -337,6 +337,13 @@ pub const ScreenSearch = struct {
|
||||
// Everything from here forward we assume is invalid because
|
||||
// our history results only get older.
|
||||
const alloc = self.allocator();
|
||||
if (self.selected) |*m| {
|
||||
const first_pruned = self.active_results.items.len + i;
|
||||
if (m.idx >= first_pruned) {
|
||||
m.deinit(self.screen);
|
||||
self.selected = null;
|
||||
}
|
||||
}
|
||||
for (self.history_results.items[i..]) |*prune_hl| prune_hl.deinit(alloc);
|
||||
self.history_results.shrinkAndFree(alloc, i);
|
||||
return;
|
||||
@@ -1497,6 +1504,38 @@ test "select after all matches disappear drops the selection" {
|
||||
try testing.expectEqual(0, search.history_results.items.len);
|
||||
}
|
||||
|
||||
test "select after partial history erase drops a pruned selection" {
|
||||
const alloc = testing.allocator;
|
||||
var t: Terminal = try .init(alloc, .{
|
||||
.cols = 10,
|
||||
.rows = 2,
|
||||
.max_scrollback = std.math.maxInt(usize),
|
||||
});
|
||||
defer t.deinit(alloc);
|
||||
const list: *PageList = &t.screens.active.pages;
|
||||
|
||||
var stream = t.vtStream();
|
||||
defer stream.deinit();
|
||||
|
||||
stream.nextSlice("error\r\n");
|
||||
const first = list.pages.first.?;
|
||||
while (list.totalPages() < 3) stream.nextSlice("\r\n");
|
||||
const first_rows = first.rows();
|
||||
|
||||
var search: ScreenSearch = try .init(alloc, t.screens.active, "error");
|
||||
defer search.deinit();
|
||||
try search.searchAll();
|
||||
try testing.expectEqual(0, search.active_results.items.len);
|
||||
try testing.expectEqual(1, search.history_results.items.len);
|
||||
try testing.expect(try search.select(.next));
|
||||
|
||||
list.eraseHistory(.{ .history = .{ .y = first_rows - 1 } });
|
||||
try testing.expect(!search.selected.?.highlight.start.garbage);
|
||||
|
||||
try testing.expect(!try search.select(.next));
|
||||
try testing.expect(search.selected == null);
|
||||
}
|
||||
|
||||
test "screen search no scrollback has no history" {
|
||||
const alloc = testing.allocator;
|
||||
var t: Terminal = try .init(alloc, .{
|
||||
|
||||
Reference in New Issue
Block a user