lattice_completion/builtins/
mod.rs1pub mod annotators;
7pub mod generators;
8pub mod matchers;
9pub mod rankers;
10
11use crate::registry::{AnnotatorId, CompletionRegistry, GeneratorId, MatcherId, RankerId};
12
13#[derive(Debug, Clone, Copy)]
17pub struct CompletionBuiltins {
18 pub gen_commands: GeneratorId,
19 pub gen_files: GeneratorId,
20 pub gen_directories: GeneratorId,
21 pub match_prefix: MatcherId,
22 pub match_substring: MatcherId,
23 pub match_fuzzy: MatcherId,
24 pub rank_score: RankerId,
25 pub rank_alphabetical: RankerId,
26 pub anno_kind_label: AnnotatorId,
27 pub anno_doc_snippet: AnnotatorId,
28}
29
30pub fn populate(registry: &mut CompletionRegistry) -> CompletionBuiltins {
34 let gen_commands = registry.register_generator(
35 "gen:commands",
36 "Every registered command (commands / motions / operators / text-objects / ex-commands).",
37 generators::CommandsGenerator,
38 );
39 let gen_files = registry.register_generator(
40 "gen:files",
41 "Filesystem entries matching the prefix's directory + basename pattern.",
42 generators::FilesGenerator,
43 );
44 let gen_directories = registry.register_generator(
45 "gen:directories",
46 "Directory entries only (like gen:files but filters out regular files).",
47 generators::DirectoriesGenerator,
48 );
49 let match_prefix = registry.register_matcher(
50 "match:prefix",
51 "Exact-prefix match. Fast + predictable.",
52 matchers::PrefixMatcher,
53 );
54 let match_substring = registry.register_matcher(
55 "match:substring",
56 "Case-insensitive substring contains.",
57 matchers::SubstringMatcher,
58 );
59 let match_fuzzy = registry.register_matcher(
60 "match:fuzzy",
61 "Subsequence fuzzy match with score-by-density.",
62 matchers::FuzzyMatcher,
63 );
64 let rank_score = registry.register_ranker(
65 "rank:score",
66 "Descending by matcher score; alphabetical tie-break.",
67 rankers::ScoreRanker,
68 );
69 let rank_alphabetical = registry.register_ranker(
70 "rank:alphabetical",
71 "Alphabetical (A-Z) on candidate text.",
72 rankers::AlphabeticalRanker,
73 );
74 let anno_kind_label = registry.register_annotator(
75 "anno:kind-label",
76 "Append `(kind)` after the candidate text -- e.g. `(motion)`, `(file)`.",
77 annotators::KindLabelAnnotator,
78 );
79 let anno_doc_snippet = registry.register_annotator(
80 "anno:doc-snippet",
81 "Append the first line of the candidate's documentation.",
82 annotators::DocSnippetAnnotator,
83 );
84
85 registry.default_matcher = Some(match_fuzzy);
91 registry.default_rankers = vec![rank_score];
95 registry.default_annotators = vec![anno_kind_label, anno_doc_snippet];
96
97 CompletionBuiltins {
98 gen_commands,
99 gen_files,
100 gen_directories,
101 match_prefix,
102 match_substring,
103 match_fuzzy,
104 rank_score,
105 rank_alphabetical,
106 anno_kind_label,
107 anno_doc_snippet,
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 #![allow(clippy::unwrap_used, clippy::panic)]
114 use super::*;
115
116 #[test]
117 fn populate_registers_all_builtins() {
118 let mut r = CompletionRegistry::new();
119 let b = populate(&mut r);
120 assert!(r.generator(b.gen_commands).is_some());
121 assert!(r.matcher(b.match_prefix).is_some());
122 assert!(r.matcher(b.match_fuzzy).is_some());
123 assert!(r.ranker(b.rank_score).is_some());
124 assert!(r.annotator(b.anno_kind_label).is_some());
125 }
126
127 #[test]
128 fn populate_sets_sensible_defaults() {
129 let mut r = CompletionRegistry::new();
130 let b = populate(&mut r);
131 assert_eq!(r.default_matcher, Some(b.match_fuzzy));
134 assert_eq!(r.default_rankers, vec![b.rank_score]);
135 assert_eq!(
136 r.default_annotators,
137 vec![b.anno_kind_label, b.anno_doc_snippet]
138 );
139 }
140
141 #[test]
142 fn registered_names_are_introspectable() {
143 let mut r = CompletionRegistry::new();
144 let _ = populate(&mut r);
145 assert!(r.generator_by_name("gen:commands").is_some());
146 assert!(r.matcher_by_name("match:fuzzy").is_some());
147 assert!(r.ranker_by_name("rank:alphabetical").is_some());
148 assert!(r.annotator_by_name("anno:kind-label").is_some());
149 }
150}