-
Notifications
You must be signed in to change notification settings - Fork 99
/
Copy pathbuilder.rs
80 lines (67 loc) · 2.21 KB
/
builder.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::{
CompletionItemKind,
context::CompletionContext,
item::CompletionItem,
relevance::{filtering::CompletionFilter, scoring::CompletionScore},
};
pub(crate) struct PossibleCompletionItem<'a> {
pub label: String,
pub description: String,
pub kind: CompletionItemKind,
pub score: CompletionScore<'a>,
pub filter: CompletionFilter<'a>,
}
pub(crate) struct CompletionBuilder<'a> {
items: Vec<PossibleCompletionItem<'a>>,
ctx: &'a CompletionContext<'a>,
}
impl<'a> CompletionBuilder<'a> {
pub fn new(ctx: &'a CompletionContext) -> Self {
CompletionBuilder { items: vec![], ctx }
}
pub fn add_item(&mut self, item: PossibleCompletionItem<'a>) {
self.items.push(item);
}
pub fn finish(self) -> Vec<CompletionItem> {
let mut items: Vec<PossibleCompletionItem> = self
.items
.into_iter()
.filter(|i| i.filter.is_relevant(self.ctx).is_some())
.collect();
for item in items.iter_mut() {
item.score.calc_score(self.ctx);
}
items.sort_by(|a, b| {
b.score
.get_score()
.cmp(&a.score.get_score())
.then_with(|| a.label.cmp(&b.label))
});
items.dedup_by(|a, b| a.label == b.label);
items.truncate(crate::LIMIT);
let should_preselect_first_item = should_preselect_first_item(&items);
items
.into_iter()
.enumerate()
.map(|(idx, item)| {
let preselected = idx == 0 && should_preselect_first_item;
CompletionItem {
description: item.description,
kind: item.kind,
label: item.label,
preselected,
score: item.score.get_score(),
}
})
.collect()
}
}
fn should_preselect_first_item(items: &Vec<PossibleCompletionItem>) -> bool {
let mut items_iter = items.iter();
let first = items_iter.next();
let second = items_iter.next();
first.is_some_and(|f| match second {
Some(s) => (f.score.get_score() - s.score.get_score()) > 10,
None => true,
})
}