neco-fuzzy
Fuzzy scoring and ranking for commands, paths, and short identifiers.
This crate owns scoring, ranking, prepared matching, and prepared candidate archives. Indexing, caches, watchers, path normalization, and UI highlighting stay with the caller.
Features
- Case-insensitive subsequence matching by default
- DP-based scoring that prefers contiguous runs, boundary hits, and basename-local matches
ScoreConfigfor tuning position, boundary, gap, span, head, and confidence weightsCorpusStatsfor optional ASCII IDF weighting- Stable one-shot API and prepared API with caller-owned scratch storage
- ASCII fast path for ASCII-heavy queries and candidates
- Prepared candidate archive for persistence and warm reload
Usage
Command search:
use ;
let candidates = ;
let mut out: = Vecnew;
top_k;
assert_eq!;
let score = score.expect;
assert!;
assert!;
Configured search:
use ;
let config = ScoreConfig ;
let candidates = ;
let mut out: = Vecnew;
top_k_with_config;
assert_eq!;
assert!;
Corpus-aware search:
use ;
let stats = from_candidates;
let config = ScoreConfig ;
let score = score_with_corpus.expect;
assert!;
Prepared search:
use ;
let query = new;
let candidates = ;
let mut scratch = default;
let mut out: = Vecnew;
top_k_prepared;
assert_eq!;
Prepared candidate archive:
use ;
let owned = new;
let mut bytes = vec!;
owned.encode_into.expect;
let restored = decode.expect;
let query = new;
let mut scratch = default;
assert!;
Ranking
top_k ranks matches in this order:
- Higher score
- Earlier match start
- Shorter candidate
- Earlier input order
Score contains three views of the same result:
value: integer score for ranking and compatibilityenergy: raw DP energy, where lower is betterconfidence: normalized confidence in(0, 1]
With a fixed query, the scorer still separates strong boundary-local matches from weak long-range subsequences:
| Query | Candidate | Value | Confidence |
|---|---|---|---|
abc |
abc |
49 |
0.615 |
abc |
abC |
40 |
0.595 |
abc |
a_b_c |
40 |
0.594 |
abc |
abc_suffix |
-14 |
0.466 |
abc |
AlphaBetaCode |
-79 |
0.320 |
abc |
prefix_abc |
-151 |
0.192 |
abc |
unrelated-text |
— |
— |
API
| Item | Description |
|---|---|
Score |
Score summary with value, energy, confidence, byte range, and matched count |
Match |
Ranked output item for top_k |
PreparedQuery |
Query prepared for repeated matching |
PreparedCandidate |
Candidate prepared for repeated matching |
OwnedPreparedCandidate |
Owned prepared candidate for persistence and warm reload |
PreparedCandidateRef |
Borrowed prepared candidate view for cache-backed execution |
PreparedCandidateHeader |
Versioned archive header for encoded candidates |
ScoreConfig |
Score weights and conversion parameters |
CorpusStats |
Corpus statistics for optional IDF weighting |
Scratch |
Reusable working storage for prepared matching |
candidate_fingerprint |
Stable fingerprint for cache reuse and invalidation checks |
score, score_case_sensitive |
One-shot scoring |
score_with_config, score_with_corpus |
One-shot scoring with explicit tuning |
score_prepared* |
Prepared scoring for borrowed and owned candidates |
match_indices* |
Matched byte offsets from DP traceback |
top_k, top_k_prepared* |
Ranking for one-shot and prepared workloads |
top_k_with_config, top_k_with_corpus |
Ranking with explicit tuning |
Notes
match_indicesreturns byte offsets, not character counts.- Prepared candidate archives keep text and fingerprint. Archive compatibility is tracked with
PreparedCandidateHeader. PREPARED_CANDIDATE_ALGORITHM_VERSIONis2in0.2.x.- See CHANGELOG.md for versioned changes.
Complexity
- Greedy subsequence filter:
O(candidate_len) - DP scoring for a matched candidate:
O(query_len * candidate_len) - Top-k selection:
O(num_candidates * log(limit))
License
MIT