Implement Outline::search

This commit is contained in:
Antonio Scandurra 2022-01-13 15:10:29 +01:00
parent 5e64f1aca8
commit 06ba1c64cf
3 changed files with 71 additions and 2 deletions

View file

@ -19,6 +19,7 @@ test-support = [
[dependencies]
clock = { path = "../clock" }
collections = { path = "../collections" }
fuzzy = { path = "../fuzzy" }
gpui = { path = "../gpui" }
lsp = { path = "../lsp" }
rpc = { path = "../rpc" }

View file

@ -1917,7 +1917,7 @@ impl BufferSnapshot {
})
.collect::<Vec<_>>();
Some(Outline(items))
Some(Outline::new(items))
}
pub fn enclosing_bracket_ranges<T: ToOffset>(

View file

@ -1,7 +1,13 @@
use std::ops::Range;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::AppContext;
#[derive(Debug)]
pub struct Outline(pub Vec<OutlineItem>);
pub struct Outline {
pub items: Vec<OutlineItem>,
candidates: Vec<StringMatchCandidate>,
}
#[derive(Clone, Debug)]
pub struct OutlineItem {
@ -11,3 +17,65 @@ pub struct OutlineItem {
pub text: String,
pub name_range_in_text: Range<usize>,
}
impl Outline {
pub fn new(items: Vec<OutlineItem>) -> Self {
Self {
candidates: items
.iter()
.map(|item| {
let text = &item.text[item.name_range_in_text.clone()];
StringMatchCandidate {
string: text.to_string(),
char_bag: text.into(),
}
})
.collect(),
items,
}
}
pub fn search(&self, query: &str, cx: &AppContext) -> Vec<StringMatch> {
let mut matches = smol::block_on(fuzzy::match_strings(
&self.candidates,
query,
true,
100,
&Default::default(),
cx.background().clone(),
));
matches.sort_unstable_by_key(|m| m.candidate_index);
let mut tree_matches = Vec::new();
let mut prev_item_ix = 0;
for mut string_match in matches {
let outline_match = &self.items[string_match.candidate_index];
for position in &mut string_match.positions {
*position += outline_match.name_range_in_text.start;
}
for (ix, item) in self.items[prev_item_ix..string_match.candidate_index]
.iter()
.enumerate()
{
let candidate_index = ix + prev_item_ix;
if item.range.contains(&outline_match.range.start)
&& item.range.contains(&outline_match.range.end)
{
tree_matches.push(StringMatch {
candidate_index,
score: Default::default(),
positions: Default::default(),
string: Default::default(),
});
}
}
prev_item_ix = string_match.candidate_index;
tree_matches.push(string_match);
}
tree_matches
}
}