Skip to main content

yuru_core/
config.rs

1/// Search and ranking configuration used by index and query execution.
2#[derive(Clone, Debug)]
3pub struct SearchConfig {
4    /// Maximum number of expanded query variants kept for one query.
5    pub max_query_variants: usize,
6    /// Maximum number of search keys kept for one candidate.
7    pub max_search_keys_per_candidate: usize,
8    /// Maximum total UTF-8 bytes for non-base search keys on one candidate.
9    pub max_total_key_bytes_per_candidate: usize,
10    /// Maximum number of results returned after ranking.
11    pub limit: usize,
12    /// Number of top candidates to rescore for quality-oriented ordering.
13    pub top_b_for_quality_score: usize,
14    /// Uses exact substring scoring instead of fuzzy subsequence scoring.
15    pub exact: bool,
16    /// Enables fzf-style extended query syntax.
17    pub extended: bool,
18    /// Preserves case during matching when true.
19    pub case_sensitive: bool,
20    /// Disables filtering and returns candidates in ranking order only.
21    pub disabled: bool,
22    /// Keeps input order instead of sorting by score.
23    pub no_sort: bool,
24    /// Adds normalized candidate and query keys.
25    pub normalize: bool,
26    /// Fuzzy matcher implementation used for scoring.
27    pub matcher_algo: MatcherAlgo,
28    /// Ordered tiebreak rules applied after score comparison.
29    pub tiebreaks: Vec<Tiebreak>,
30}
31
32/// Candidate-key generation budget passed to language backends.
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub struct KeyBudget {
35    /// Maximum number of generated search keys to produce for one candidate.
36    pub max_keys: usize,
37    /// Maximum bytes and mapped characters generated by one language backend.
38    pub max_total_bytes: usize,
39}
40
41/// Query-variant generation budget passed to language backends.
42#[derive(Clone, Copy, Debug, Eq, PartialEq)]
43pub struct QueryBudget {
44    /// Maximum number of query variants to produce for one query.
45    pub max_variants: usize,
46}
47
48impl SearchConfig {
49    /// Returns the candidate-key generation budget represented by this config.
50    pub fn key_budget(&self) -> KeyBudget {
51        KeyBudget {
52            max_keys: self.max_search_keys_per_candidate,
53            max_total_bytes: self.max_total_key_bytes_per_candidate,
54        }
55    }
56
57    /// Returns the query-variant generation budget represented by this config.
58    pub fn query_budget(&self) -> QueryBudget {
59        QueryBudget {
60            max_variants: self.max_query_variants,
61        }
62    }
63}
64
65impl Default for KeyBudget {
66    fn default() -> Self {
67        SearchConfig::default().key_budget()
68    }
69}
70
71impl Default for QueryBudget {
72    fn default() -> Self {
73        SearchConfig::default().query_budget()
74    }
75}
76
77/// Matcher implementation selected for fuzzy scoring.
78#[derive(Clone, Copy, Debug, Eq, PartialEq)]
79pub enum MatcherAlgo {
80    /// Yuru's default greedy matcher.
81    Greedy,
82    /// Greedy fzf-style matcher alias.
83    FzfV1,
84    /// Nucleo-backed quality matcher alias.
85    FzfV2,
86    /// Nucleo-backed quality matcher.
87    Nucleo,
88}
89
90/// Secondary sort rule used when scores are equal.
91#[derive(Clone, Copy, Debug, Eq, PartialEq)]
92pub enum Tiebreak {
93    /// Prefer shorter display strings.
94    Length,
95    /// Prefer fewer separated match chunks.
96    Chunk,
97    /// Prefer path-like matches with better pathname position.
98    Pathname,
99    /// Prefer matches closer to the beginning.
100    Begin,
101    /// Prefer matches closer to the end.
102    End,
103    /// Prefer lower original candidate index.
104    Index,
105}
106
107impl Default for SearchConfig {
108    fn default() -> Self {
109        Self {
110            max_query_variants: 8,
111            max_search_keys_per_candidate: 8,
112            max_total_key_bytes_per_candidate: 1024,
113            limit: 10,
114            top_b_for_quality_score: 1000,
115            exact: false,
116            extended: true,
117            case_sensitive: false,
118            disabled: false,
119            no_sort: false,
120            normalize: true,
121            matcher_algo: MatcherAlgo::Greedy,
122            tiebreaks: vec![Tiebreak::Length, Tiebreak::Index],
123        }
124    }
125}