The main-loop mirror of the X-button clear was level-triggered:
'FindQuery=="" && widget has text'. But the widget updates on every
keystroke while the logic only stores the query a round-trip later, so any
frame drawn in that window still carried FindQuery=="" and wiped the input
- the periodic self-clearing.
Make it edge-triggered: FindState.ClearSeq bumps once per clear; the frame
carries it as FindClearSeq; main wipes the widget input once per NEW value
(lastFindClearSeq handshake). findClear bumps it; findReset preserves it
(main tracks it monotonically, so a reset to 0 would swallow a later clear).
Tests: unit asserts the bump, monotonicity, and close/reopen preservation.
The X was redundant with the top-bar search icon (both closed the bar).
Now the X empties the query and results but leaves the bar open; closing
is the search icon's toggle.
- editor: new findClear (empties query/matches, bumps Gen so an in-flight
scan of the old query is dropped, disarms the settle) and FindClear
handler; the X icon now runs FindClear.
- main: mirrors the logic-side clear into the main-owned widget input
(frame.FindQuery=="" while the widget still has text -> SetText("")).
- tests: unit findClear (stays open, supersedes in-flight scan); e2e X
clears but keeps the bar open and focus, close now via ToggleFind.
- doc: spec updated (clear button vs icon toggle).
- pool: SearchTask + FindSubstring (case-insensitive substring scan with
query generation for stale-result dropping)
- editor: FindState on EditorState; find bar handlers (ToggleFind/FindNext/
FindPrev/FindClose); worker-pool scan of the in-memory content; edit-aware
offset remapping (shift after, drop overlapping); next/prev with
wrap-around, selection + scroll to match; main-owned find_bar input
forwarded via FindQueryChan (browser search_bar precedent)
- ui: find-bar layout below the margin-free top bar; search icon on the top
bar right; new search/close/chevron_up/chevron_down icons
- logic: findQueryChan, TypeSearch result handling, findReset on open
- frame: FindQuery field (main syncs the widget text like Query)
- tests: pool scan tests, find-state unit tests (remap, nav, gen gate,
focus), e2e find bar + navigation + edit-survival on real files
- docs: spec/architecture/development_plan updated (search implemented,
channel/task tables)