2022-01-13 14:10:29 +00:00
|
|
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
2022-01-13 22:46:15 +00:00
|
|
|
use gpui::{executor::Background, fonts::HighlightStyle};
|
2022-01-13 22:04:25 +00:00
|
|
|
use std::{ops::Range, sync::Arc};
|
2022-01-13 14:10:29 +00:00
|
|
|
|
2022-01-13 02:17:19 +00:00
|
|
|
#[derive(Debug)]
|
2022-01-13 17:24:00 +00:00
|
|
|
pub struct Outline<T> {
|
|
|
|
pub items: Vec<OutlineItem<T>>,
|
2022-01-13 14:10:29 +00:00
|
|
|
candidates: Vec<StringMatchCandidate>,
|
|
|
|
}
|
2022-01-13 02:17:19 +00:00
|
|
|
|
2022-01-13 11:01:11 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2022-01-13 17:24:00 +00:00
|
|
|
pub struct OutlineItem<T> {
|
2022-01-13 10:35:43 +00:00
|
|
|
pub depth: usize,
|
2022-01-13 17:24:00 +00:00
|
|
|
pub range: Range<T>,
|
2022-01-13 02:17:19 +00:00
|
|
|
pub text: String,
|
2022-01-14 02:09:54 +00:00
|
|
|
pub name_ranges: Vec<Range<u32>>,
|
|
|
|
pub highlight_ranges: Vec<(Range<usize>, HighlightStyle)>,
|
2022-01-13 02:17:19 +00:00
|
|
|
}
|
2022-01-13 14:10:29 +00:00
|
|
|
|
2022-01-13 17:24:00 +00:00
|
|
|
impl<T> Outline<T> {
|
|
|
|
pub fn new(items: Vec<OutlineItem<T>>) -> Self {
|
2022-01-13 14:10:29 +00:00
|
|
|
Self {
|
|
|
|
candidates: items
|
|
|
|
.iter()
|
|
|
|
.map(|item| {
|
2022-01-13 22:04:25 +00:00
|
|
|
let text = item
|
|
|
|
.name_ranges
|
|
|
|
.iter()
|
|
|
|
.map(|range| &item.text[range.start as usize..range.end as usize])
|
|
|
|
.collect::<String>();
|
2022-01-13 14:10:29 +00:00
|
|
|
StringMatchCandidate {
|
2022-01-13 22:04:25 +00:00
|
|
|
char_bag: text.as_str().into(),
|
|
|
|
string: text,
|
2022-01-13 14:10:29 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
items,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 22:04:25 +00:00
|
|
|
pub async fn search(&self, query: &str, executor: Arc<Background>) -> Vec<StringMatch> {
|
|
|
|
let mut matches = fuzzy::match_strings(
|
2022-01-13 14:10:29 +00:00
|
|
|
&self.candidates,
|
|
|
|
query,
|
|
|
|
true,
|
|
|
|
100,
|
|
|
|
&Default::default(),
|
2022-01-13 22:04:25 +00:00
|
|
|
executor,
|
|
|
|
)
|
|
|
|
.await;
|
2022-01-13 14:10:29 +00:00
|
|
|
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];
|
2022-01-13 22:04:25 +00:00
|
|
|
|
|
|
|
let mut name_ranges = outline_match.name_ranges.iter();
|
|
|
|
let mut name_range = name_ranges.next().unwrap();
|
|
|
|
let mut preceding_ranges_len = 0;
|
2022-01-13 14:10:29 +00:00
|
|
|
for position in &mut string_match.positions {
|
2022-01-13 22:04:25 +00:00
|
|
|
while *position >= preceding_ranges_len + name_range.len() as usize {
|
|
|
|
preceding_ranges_len += name_range.len();
|
|
|
|
name_range = name_ranges.next().unwrap();
|
|
|
|
}
|
|
|
|
*position = name_range.start as usize + (*position - preceding_ranges_len);
|
2022-01-13 14:10:29 +00:00
|
|
|
}
|
|
|
|
|
2022-01-14 08:12:30 +00:00
|
|
|
let insertion_ix = tree_matches.len();
|
2022-01-13 15:59:52 +00:00
|
|
|
let mut cur_depth = outline_match.depth;
|
2022-01-13 14:10:29 +00:00
|
|
|
for (ix, item) in self.items[prev_item_ix..string_match.candidate_index]
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2022-01-13 15:59:52 +00:00
|
|
|
.rev()
|
2022-01-13 14:10:29 +00:00
|
|
|
{
|
2022-01-13 15:59:52 +00:00
|
|
|
if cur_depth == 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-01-13 14:10:29 +00:00
|
|
|
let candidate_index = ix + prev_item_ix;
|
2022-01-13 15:59:52 +00:00
|
|
|
if item.depth == cur_depth - 1 {
|
2022-01-14 08:12:30 +00:00
|
|
|
tree_matches.insert(
|
|
|
|
insertion_ix,
|
|
|
|
StringMatch {
|
|
|
|
candidate_index,
|
|
|
|
score: Default::default(),
|
|
|
|
positions: Default::default(),
|
|
|
|
string: Default::default(),
|
|
|
|
},
|
|
|
|
);
|
2022-01-13 15:59:52 +00:00
|
|
|
cur_depth -= 1;
|
2022-01-13 14:10:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 15:59:52 +00:00
|
|
|
prev_item_ix = string_match.candidate_index + 1;
|
2022-01-13 14:10:29 +00:00
|
|
|
tree_matches.push(string_match);
|
|
|
|
}
|
|
|
|
|
|
|
|
tree_matches
|
|
|
|
}
|
|
|
|
}
|