Skip to main content

FindState

Struct FindState 

Source
pub struct FindState { /* private fields */ }
Expand description

The search view-state: the active query, the active match’s decoration id, and the coverage/cap bookkeeping.

The one design rule: the store IS the match set — the sorted FindMatch decorations, in (start, id) = document order. This state deliberately holds no handle list; count, order, and N-of-M all derive from store queries (one fact, one owner). The set is repaired eagerly per commit via FindState::on_commit, so it is always current — undo/redo inherit the repair through the shared view-rebase mover.

Implementations§

Source§

impl FindState

Source

pub fn new() -> Self

An empty state — no query, no matches.

Source

pub fn query(&self) -> Option<&FindQuery>

The active query, or None if find is idle.

Source

pub fn match_count(&self, store: &DecorationStore) -> usize

How many live matches the current query has — the store IS the match set, so this is the O(1) root-summary find_count read.

Source

pub fn active_id(&self) -> Option<DecorationId>

The decoration handle of the active match, if any — the render layer compares each FindMatch decoration to this to pick the distinct style.

Source

pub fn capped(&self) -> bool

Whether the match set is a capped prefix of the document (FIND_MATCH_CAP).

Source

pub fn scope(&self) -> Option<Range<u32>>

The find-in-selection scope — matches exist only inside it. None means the whole document.

Source

pub fn set_scope( &mut self, scope: Option<Range<u32>>, buffer: &Buffer, store: &mut DecorationStore, now_ms: u64, )

Set (or clear with None) the find-in-selection scope, re-scanning synchronously — the scope is part of what matches, so changing it is a query change, not a display filter.

An empty range clears the scope rather than pinning zero matches forever: searching everything is a recoverable surprise, silently searching nothing is not. A scope equal to the current one is a no-op.

Source

pub fn set_query( &mut self, query: Option<FindQuery>, buffer: &Buffer, store: &mut DecorationStore, now_ms: u64, )

Set (or clear with None) the query and scan synchronously; never scrolls, and clears the active match. A query equal to the current one is a no-op (no needless re-scan).

The full scan runs scan_buffer — whole-document in coverage but windowed in memory, and a capped dense query stops at O(bytes-until-cap) instead of copying the rope’s tail.

Source

pub fn pattern_error(&self) -> Option<&str>

Why the current pattern does not parse, if it does not — for the find bar to show. None whenever the query is matching normally (including when it simply has no hits).

Source

pub fn maybe_rescan( &mut self, buffer: &Buffer, store: &mut DecorationStore, now_ms: u64, ) -> bool

Refill a capped match set: re-scan iff a query is active, the set is capped with room below the cap, and the debounce window has elapsed. now_ms is an injected monotonic clock — the widget passes real time, the headless suite a fake. Returns whether it scanned.

Because the eager per-commit repair keeps the set current, the only job here is growing a capped set’s coverage after matches inside it died.

Source

pub fn on_commit( &mut self, patch: &Patch, buffer: &Buffer, store: &mut DecorationStore, )

Repair the match set around a committed patch — the mover hook called from the view-rebase path AFTER DecorationStore::apply_patch (it needs post-patch positions). No-op when find is idle.

The influence window depends on the matcher. A literal query (post-edit coordinates, k = needle byte length): every affected placement must overlap new.start−(k−1) .. new.end+(k−1) (a created/destroyed match contains a changed byte or the join point). A line-scoped query (whole-word / regex) instead repairs the whole lines the edit touched — a match cannot cross a newline, so nothing off those lines can have changed — with no k−1 widening and no anchor/guard (the greedy phase the widening repairs does not exist there). The rest of this describes the literal path. Matches touching the window are removed wholesale (DecorationStore::take_matching_in); the re-scan zone is then the window widened (a) to the removed extents — a merely-touching match must be re-findable, not lost — and (b) a further k−1 bytes each way, because a placement overlapping the removal zone (one whose old greedy blocker just died — the self-overlap phase repair) can start up to k−1 bytes left of it and end as far right. Two clamps keep the zone from double-owning text: the scan starts at the last surviving match ending in the left margin (the anchor), and candidates overlapping the first surviving match right of the zone are dropped (the guard). The zone is greedily re-scanned with the same pure scan and batch-reinserted. Matches outside every zone keep their decoration ids (id stability is what lets the active match survive unrelated edits).

Active survival: untouched active stays (same id); an active removed by a window transfers to a re-created match at its exact post-patch start; otherwise it clears.

Cap: coverage_end rides the patch first; windows clamp to it, so repairs beyond a capped set’s coverage are skipped (the refill’s job). If a repair pushes the live count past FIND_MATCH_CAP, the tail is trimmed so the set stays a prefix of the document.

Source

pub fn find_next( &mut self, head: u32, selection: Range<u32>, store: &DecorationStore, ) -> Option<Range<u32>>

Select the next match from the caret and return its live range. The set is always current, so this is a pure store walk. head/selection are the newest selection’s head and extent.

Source

pub fn find_prev( &mut self, head: u32, selection: Range<u32>, store: &DecorationStore, ) -> Option<Range<u32>>

Select the previous match from the caret — the find_next mirror.

Trait Implementations§

Source§

impl Debug for FindState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for FindState

Source§

fn default() -> FindState

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.