terminal: search should use active area dirty tracking

pull/9687/head
Mitchell Hashimoto 2025-11-15 20:47:42 -08:00
parent 72921741e8
commit 061d157b50
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
3 changed files with 27 additions and 0 deletions

View File

@ -112,6 +112,16 @@ flags: packed struct {
/// True if the terminal should perform selection scrolling.
selection_scroll: bool = false,
/// Dirty flag used only by the search thread. The renderer is expected
/// to set this to true if the viewport was dirty as it was rendering.
/// This is used by the search thread to more efficiently re-search the
/// viewport and active area.
///
/// Since the renderer is going to inspect the viewport/active area ANYWAYS,
/// this lets our search thread do less work and hold the lock less time,
/// resulting in more throughput for everything.
search_viewport_dirty: bool = false,
/// Dirty flags for the renderer.
dirty: Dirty = .{},
} = .{},

View File

@ -419,6 +419,10 @@ const Search = struct {
var vp: ViewportSearch = try .init(alloc, needle);
errdefer vp.deinit();
// We use dirty tracking for active area changes. Start with it
// dirty so the first change is re-searched.
vp.active_dirty = true;
return .{
.viewport = vp,
.screens = .init(.{}),
@ -553,6 +557,15 @@ const Search = struct {
}
}
// See the `search_viewport_dirty` flag on the terminal to know
// what exactly this is for. But, if this is set, we know the renderer
// found the viewport/active area dirty, so we should mark it as
// dirty in our viewport searcher so it forces a re-search.
if (t.flags.search_viewport_dirty) {
self.viewport.active_dirty = true;
t.flags.search_viewport_dirty = false;
}
// Check our viewport for changes.
if (self.viewport.update(&t.screens.active.pages)) |updated| {
if (updated) self.stale_viewport_matches = true;

View File

@ -125,6 +125,10 @@ pub const ViewportSearch = struct {
self.fingerprint = null;
}
// If our active area was set as dirty, we always unset it here
// because we're re-searching now.
if (self.active_dirty) |*v| v.* = false;
// Clear our previous sliding window
self.window.clearAndRetainCapacity();