code wiki / (root) / nx_search_snippet_extract.nx

nx_search_snippet_extract.nx

buildroot/runtime/nx_search_snippet_extract.nx

11398 B298 linesdepth 5pulls 7 transitivereach 13 importersview sourcekind librarytopic search
docsdependenciesstructsconstsfunctions

about

nx_search_snippet_extract.nx -- V1 search snippet extractor. Context window around query-term matches + <mark>...</mark> highlight. COMPOSES (per NISHI_SMALL_SHARP_COMPOSABLE_STANDARD §4.1 M7): hub/nx_search_query_parser (NxSearchQuery + iter accessors) nx_html_escape (html_escape for safe emit) nx_search_inverted (lowercase + token-char convention) COMPOSED BY: wiki/nx_wiki_search_render (next commit) (future) any site rendering search results Status: V1. 2026-05-27. WINNER-TIER: BASELINE-C provisional INCUMBENTS: Lucene's PostingsHighlighter / FastVectorHighlighter, Tantivy's SnippetGenerator, Bleve's SearchResult.Hit Fragments, Whoosh's whoosh.highlight, Algolia's _snippetResult NUMBERS: V1 ships first-match-centered window + per-term <mark>; paired latency bench vs Lucene Postings- Highlighter pending real workload GAP: Lucene picks densest-cluster window (more relevant snippet); V1 picks first-match (simpler, deterministic). V2 ships densest-cluster scorer. PLAN: M-next: V2 cluster-density window picker per charter §5.2 EXEMPTION REASON: n/a; provisional pending measurement V1 SCOPE per NISHI_SEARCH_CHARTER.md §5.1: - Caller-allocated output buffer - Case-insensitive term matching (ASCII lowercase fold) - Window: NX_SSE_WIN_BEFORE bytes before first match + NX_SSE_WIN_AFTER bytes after; clipped to doc bounds - Each query-term occurrence inside the window wrapped in <mark>...</mark>; rest of bytes html_escape'd - "..." prefix/suffix when window doesn't reach doc bounds - Empty doc + empty query both well-defined (no error) V2 SCOPE (TODO):

dependencies 4 imports · 2 importers

nx_syscalls.nx nx_search_query_parser.nx nx_search_inverted.nx nx_html_escape.nx nx_search_snippet_extract.nx nx_search_render_html.nx nx_wiki_answer.nx

imports: nx_syscalls.nxnx_search_query_parser.nxnx_search_inverted.nxnx_html_escape.nx

imported by: nx_search_render_html.nxnx_wiki_answer.nx

structs

none

consts

52const NX_SSE_OK: i64 = 0
53const NX_SSE_BAD_INPUT: i64 = 1700
54const NX_SSE_OUTPUT_OVERFLOW: i64 = 1701
55const NX_SSE_DOC_TOO_LARGE: i64 = 1702
56const NX_SSE_LOOP_BUDGET: i64 = 1703
57const NX_SSE_ESCAPE_FAIL: i64 = 1704
58const NX_SSE_NOT_IMPLEMENTED: i64 = 1705
61const NX_SSE_WIN_BEFORE: i64 = 64
62const NX_SSE_WIN_AFTER: i64 = 192
63const NX_SSE_DEFAULT_OUTPUT_CAP: i64 = 2048
64const NX_SSE_MAX_DOC_BYTES: i64 = 1048576 // 1 MB cap per snippet input
65const NX_SSE_LOOP_BUDGET_CAP: i64 = 10000000
66const NX_SSE_ELLIPSIS: *u8 = "..." as *u8
67const NX_SSE_ELLIPSIS_N: i64 = 3
68const NX_SSE_MARK_OPEN: *u8 = "<mark>" as *u8
69const NX_SSE_MARK_OPEN_N: i64 = 6
70const NX_SSE_MARK_CLOSE: *u8 = "</mark>" as *u8
71const NX_SSE_MARK_CLOSE_N: i64 = 7
72const NX_SSE_MAX_TERMS_CONSIDER: i64 = 32

functions

76func nx_sse_lower(c: i64) -> i64
called by 1: nx_sse_match_at
86func nx_sse_match_at(src: *u8, src_n: i64, pos: i64,
107func nx_sse_find_first_match(src: *u8, src_n: i64,
148func nx_sse_match_len_at(src: *u8, src_n: i64, pos: i64,
175func nx_sse_put_raw(out: *u8, cap: i64, off: i64,
190func nx_sse_put_escaped(out: *u8, cap: i64, off: i64,
205func nx_search_snippet_extract(out: *u8, out_cap: i64,