terminal: ScreenSearch can omit overlapped results in history tick

pull/9585/head
Mitchell Hashimoto 2025-11-14 07:24:02 -08:00
parent d349cc8932
commit 6b805a318e
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
1 changed files with 15 additions and 35 deletions

View File

@ -122,28 +122,12 @@ pub const ScreenSearch = struct {
/// Returns all matches as an owned slice (caller must free). /// Returns all matches as an owned slice (caller must free).
/// The matches are ordered from most recent to oldest (e.g. bottom /// The matches are ordered from most recent to oldest (e.g. bottom
/// of the screen to top of the screen). /// of the screen to top of the screen).
///
/// This handles pruning overlapping results between active area
/// and the history area so you should use this instead of accessing
/// the result slices directly.
pub fn matches( pub fn matches(
self: *ScreenSearch, self: *ScreenSearch,
alloc: Allocator, alloc: Allocator,
) Allocator.Error![]Selection { ) Allocator.Error![]Selection {
const active_results = self.active_results.items; const active_results = self.active_results.items;
const history_results: []const Selection = if (self.history) |*h| history_results: { const history_results = self.history_results.items;
// We prune all the history results that start in our first
// history page because the active area will overlap and
// get that.
for (self.history_results.items, 0..) |sel, i| {
if (sel.start().node != h.start_pin.node) {
break :history_results self.history_results.items[i..];
}
}
break :history_results &.{};
} else &.{};
const results = try alloc.alloc( const results = try alloc.alloc(
Selection, Selection,
active_results.len + history_results.len, active_results.len + history_results.len,
@ -252,7 +236,7 @@ pub const ScreenSearch = struct {
} }
fn tickHistory(self: *ScreenSearch) Allocator.Error!void { fn tickHistory(self: *ScreenSearch) Allocator.Error!void {
const history: *PageListSearch = if (self.history) |*h| &h.searcher else { const history: *HistorySearch = if (self.history) |*h| h else {
// No history to search, we're done. // No history to search, we're done.
self.state = .complete; self.state = .complete;
return; return;
@ -261,7 +245,11 @@ pub const ScreenSearch = struct {
// Try to consume all the loaded matches in one go, because // Try to consume all the loaded matches in one go, because
// the search is generally fast for loaded data. // the search is generally fast for loaded data.
const alloc = self.allocator(); const alloc = self.allocator();
while (history.next()) |sel| { while (history.searcher.next()) |sel| {
// Ignore selections that are found within the starting
// node since those are covered by the active area search.
if (sel.start().node == history.start_pin.node) continue;
// Same note as tickActive for error handling. // Same note as tickActive for error handling.
try self.history_results.append(alloc, sel); try self.history_results.append(alloc, sel);
} }
@ -332,12 +320,6 @@ pub const ScreenSearch = struct {
break :history; break :history;
} }
// We had prior history with a valid pin and our current
// starting history node doesn't match our previous. So there is
// a small delta (usually small) that we need to search and update
// our history results.
const old_node = history.start_pin.node;
// Do a forward search from our prior node to this one. We // Do a forward search from our prior node to this one. We
// collect all the results into a new list. We ASSUME that // collect all the results into a new list. We ASSUME that
// reloadActive is being called frequently enough that there isn't // reloadActive is being called frequently enough that there isn't
@ -362,10 +344,13 @@ pub const ScreenSearch = struct {
self.history_results.items.len, self.history_results.items.len,
); );
errdefer results.deinit(alloc); errdefer results.deinit(alloc);
while (window.next()) |sel| try results.append( while (window.next()) |sel| {
alloc, if (sel.start().node == history_node) continue;
sel, try results.append(
); alloc,
sel,
);
}
// If we have no matches then there is nothing to change // If we have no matches then there is nothing to change
// in our history (fast path) // in our history (fast path)
@ -374,12 +359,7 @@ pub const ScreenSearch = struct {
// Matches! Reverse our list then append all the remaining // Matches! Reverse our list then append all the remaining
// history items that didn't start on our original node. // history items that didn't start on our original node.
std.mem.reverse(Selection, results.items); std.mem.reverse(Selection, results.items);
for (self.history_results.items, 0..) |sel, i| { try results.appendSlice(alloc, self.history_results.items);
if (sel.start().node != old_node) {
try results.appendSlice(alloc, self.history_results.items[i..]);
break;
}
}
self.history_results.deinit(alloc); self.history_results.deinit(alloc);
self.history_results = results; self.history_results = results;
} }