Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Candidates and regex analysis

A search never scans the whole corpus. It first computes a candidate set from the trigram index, then reads only those files.

Plain text

The query is case-folded (Unicode simple case folding, the fold ripgrep’s -i uses, which is lowercase except for a few letters such as ſ and µ; the index stores folded text) and split into overlapping three-byte windows; parse_query yields par, ars, rse, se_, e_q, _qu, que, uer, ery. Each trigram has a posting list (a Roaring bitmap of file ids); intersecting them gives every file that could contain the query, independent of corpus size. Several words are one phrase, so their trigrams (spaces included) are intersected the same way.

Queries shorter than three characters have no trigrams and fall back to all files, bounded by the match budget and ranking mode.

Regex

The pattern is parsed into a syntax tree and walked for required literals: text that every match must contain. Alternations contribute the union of their branches’ literals (each branch must have one), optional groups contribute nothing, and a repetition ends a literal run (so fo+bar requires fo and obar, never fobar). Case-insensitive patterns lower every literal, with (?i) handled through simple case folding so k and s do not break a run. The literals’ trigrams filter the candidates exactly as a text query would; a pattern with no required literal of three or more bytes scans everything.

A property test in the suite asserts that for every pattern the candidate set is a superset of the files the compiled regex actually matches.

Verification and modes

Candidates are then read and verified: the text query is searched with a whole-buffer scan (memchr-based, or a Unicode case fold when needed) that resolves line boundaries only at hits; a regex is compiled once per query with (?mR) and run in one pass per file with one hit per line. Symbol queries match definition names; reference queries look up the interned identifier in each candidate’s reference table and verify the position against the current content.

Budgets

Every search runs under a QueryRun: a match budget derived from the page size and offset ([search] min_match_budget, match_budget_multiplier, max_match_budget), and a deadline just under the request timeout. When either stops the scan the response says so (truncated_by_budget). A deep page gets a budget that reaches it, so paging past search.max_page_offset (100,000 by default) is refused rather than allowed to grow the budget without bound.