run_search() replaces collecting every match in the buffer (and building
the full list again for every next/previous):
- Plain search finds forward from the search origin (then the current
match) in the materialized text, or backwards through 1 MiB blocks
searched forward (string_view::rfind scans a byte at a time: 511 ms
per previous-match on 105 MB, now 6 ms). Regex search walks lines
from the position with early exit.
- The i/N count stops at 1,000 matches, and for regex after 4 MiB; the
status says 'N+' when capped.
- The first match is the first at or after the cursor (it was the first
in the buffer). Extending the query keeps the current match while it
still matches. Left/Right also step through matches in the regex
replace prompt; Up/Down in a regex prompt use the regex.
On a 26 MB file: plain keystroke 30 ms -> 0.1 ms, next 24 -> 3 ms, regex
keystroke 434 -> 1.6 ms, regex next 420 -> 66 ms.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB