Associate StringMatchCandidate with an id

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-01-14 14:55:03 +01:00
parent e538beb920
commit be24e58926
5 changed files with 26 additions and 31 deletions

View file

@ -55,6 +55,7 @@ pub struct PathMatch {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StringMatchCandidate { pub struct StringMatchCandidate {
pub id: usize,
pub string: String, pub string: String,
pub char_bag: CharBag, pub char_bag: CharBag,
} }
@ -109,7 +110,7 @@ impl<'a> MatchCandidate for &'a StringMatchCandidate {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StringMatch { pub struct StringMatch {
pub candidate_index: usize, pub candidate_id: usize,
pub score: f64, pub score: f64,
pub positions: Vec<usize>, pub positions: Vec<usize>,
pub string: String, pub string: String,
@ -134,7 +135,7 @@ impl Ord for StringMatch {
self.score self.score
.partial_cmp(&other.score) .partial_cmp(&other.score)
.unwrap_or(Ordering::Equal) .unwrap_or(Ordering::Equal)
.then_with(|| self.candidate_index.cmp(&other.candidate_index)) .then_with(|| self.candidate_id.cmp(&other.candidate_id))
} }
} }
@ -198,7 +199,6 @@ pub async fn match_strings(
max_results, max_results,
); );
matcher.match_strings( matcher.match_strings(
segment_start,
&candidates[segment_start..segment_end], &candidates[segment_start..segment_end],
results, results,
cancel_flag, cancel_flag,
@ -321,7 +321,6 @@ impl<'a> Matcher<'a> {
pub fn match_strings( pub fn match_strings(
&mut self, &mut self,
start_index: usize,
candidates: &[StringMatchCandidate], candidates: &[StringMatchCandidate],
results: &mut Vec<StringMatch>, results: &mut Vec<StringMatch>,
cancel_flag: &AtomicBool, cancel_flag: &AtomicBool,
@ -329,12 +328,11 @@ impl<'a> Matcher<'a> {
self.match_internal( self.match_internal(
&[], &[],
&[], &[],
start_index,
candidates.iter(), candidates.iter(),
results, results,
cancel_flag, cancel_flag,
|candidate_index, candidate, score| StringMatch { |candidate, score| StringMatch {
candidate_index, candidate_id: candidate.id,
score, score,
positions: Vec::new(), positions: Vec::new(),
string: candidate.string.to_string(), string: candidate.string.to_string(),
@ -358,11 +356,10 @@ impl<'a> Matcher<'a> {
self.match_internal( self.match_internal(
&prefix, &prefix,
&lowercase_prefix, &lowercase_prefix,
0,
path_entries, path_entries,
results, results,
cancel_flag, cancel_flag,
|_, candidate, score| PathMatch { |candidate, score| PathMatch {
score, score,
worktree_id: tree_id, worktree_id: tree_id,
positions: Vec::new(), positions: Vec::new(),
@ -376,19 +373,18 @@ impl<'a> Matcher<'a> {
&mut self, &mut self,
prefix: &[char], prefix: &[char],
lowercase_prefix: &[char], lowercase_prefix: &[char],
start_index: usize,
candidates: impl Iterator<Item = C>, candidates: impl Iterator<Item = C>,
results: &mut Vec<R>, results: &mut Vec<R>,
cancel_flag: &AtomicBool, cancel_flag: &AtomicBool,
build_match: F, build_match: F,
) where ) where
R: Match, R: Match,
F: Fn(usize, &C, f64) -> R, F: Fn(&C, f64) -> R,
{ {
let mut candidate_chars = Vec::new(); let mut candidate_chars = Vec::new();
let mut lowercase_candidate_chars = Vec::new(); let mut lowercase_candidate_chars = Vec::new();
for (candidate_ix, candidate) in candidates.enumerate() { for candidate in candidates {
if !candidate.has_chars(self.query_char_bag) { if !candidate.has_chars(self.query_char_bag) {
continue; continue;
} }
@ -422,7 +418,7 @@ impl<'a> Matcher<'a> {
); );
if score > 0.0 { if score > 0.0 {
let mut mat = build_match(start_index + candidate_ix, &candidate, score); let mut mat = build_match(&candidate, score);
if let Err(i) = results.binary_search_by(|m| mat.cmp(&m)) { if let Err(i) = results.binary_search_by(|m| mat.cmp(&m)) {
if results.len() < self.max_results { if results.len() < self.max_results {
mat.set_positions(self.match_positions.clone()); mat.set_positions(self.match_positions.clone());

View file

@ -21,7 +21,9 @@ impl<T> Outline<T> {
Self { Self {
candidates: items candidates: items
.iter() .iter()
.map(|item| StringMatchCandidate { .enumerate()
.map(|(id, item)| StringMatchCandidate {
id,
char_bag: item.text.as_str().into(), char_bag: item.text.as_str().into(),
string: item.text.clone(), string: item.text.clone(),
}) })
@ -37,19 +39,19 @@ impl<T> Outline<T> {
true, true,
100, 100,
&Default::default(), &Default::default(),
executor, executor.clone(),
) )
.await; .await;
matches.sort_unstable_by_key(|m| m.candidate_index); matches.sort_unstable_by_key(|m| m.candidate_id);
let mut tree_matches = Vec::new(); let mut tree_matches = Vec::new();
let mut prev_item_ix = 0; let mut prev_item_ix = 0;
for string_match in matches { for string_match in matches {
let outline_match = &self.items[string_match.candidate_index]; let outline_match = &self.items[string_match.candidate_id];
let insertion_ix = tree_matches.len(); let insertion_ix = tree_matches.len();
let mut cur_depth = outline_match.depth; let mut cur_depth = outline_match.depth;
for (ix, item) in self.items[prev_item_ix..string_match.candidate_index] for (ix, item) in self.items[prev_item_ix..string_match.candidate_id]
.iter() .iter()
.enumerate() .enumerate()
.rev() .rev()
@ -63,7 +65,7 @@ impl<T> Outline<T> {
tree_matches.insert( tree_matches.insert(
insertion_ix, insertion_ix,
StringMatch { StringMatch {
candidate_index, candidate_id: candidate_index,
score: Default::default(), score: Default::default(),
positions: Default::default(), positions: Default::default(),
string: Default::default(), string: Default::default(),
@ -73,7 +75,7 @@ impl<T> Outline<T> {
} }
} }
prev_item_ix = string_match.candidate_index + 1; prev_item_ix = string_match.candidate_id + 1;
tree_matches.push(string_match); tree_matches.push(string_match);
} }

View file

@ -401,12 +401,7 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
.await; .await;
matches matches
.into_iter() .into_iter()
.map(|mat| { .map(|mat| (outline.items[mat.candidate_id].text.as_str(), mat.positions))
(
outline.items[mat.candidate_index].text.as_str(),
mat.positions,
)
})
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
} }

View file

@ -202,7 +202,7 @@ impl OutlineView {
self.list_state.scroll_to(self.selected_match_index); self.list_state.scroll_to(self.selected_match_index);
if navigate { if navigate {
let selected_match = &self.matches[self.selected_match_index]; let selected_match = &self.matches[self.selected_match_index];
let outline_item = &self.outline.items[selected_match.candidate_index]; let outline_item = &self.outline.items[selected_match.candidate_id];
self.symbol_selection_id = self.active_editor.update(cx, |active_editor, cx| { self.symbol_selection_id = self.active_editor.update(cx, |active_editor, cx| {
let snapshot = active_editor.snapshot(cx).display_snapshot; let snapshot = active_editor.snapshot(cx).display_snapshot;
let buffer_snapshot = &snapshot.buffer_snapshot; let buffer_snapshot = &snapshot.buffer_snapshot;
@ -275,7 +275,7 @@ impl OutlineView {
.iter() .iter()
.enumerate() .enumerate()
.map(|(index, _)| StringMatch { .map(|(index, _)| StringMatch {
candidate_index: index, candidate_id: index,
score: Default::default(), score: Default::default(),
positions: Default::default(), positions: Default::default(),
string: Default::default(), string: Default::default(),
@ -366,7 +366,7 @@ impl OutlineView {
} else { } else {
&settings.theme.selector.item &settings.theme.selector.item
}; };
let outline_item = &self.outline.items[string_match.candidate_index]; let outline_item = &self.outline.items[string_match.candidate_id];
Text::new(outline_item.text.clone(), style.label.text.clone()) Text::new(outline_item.text.clone(), style.label.text.clone())
.with_soft_wrap(false) .with_soft_wrap(false)

View file

@ -157,7 +157,9 @@ impl ThemeSelector {
let candidates = self let candidates = self
.themes .themes
.list() .list()
.map(|name| StringMatchCandidate { .enumerate()
.map(|(id, name)| StringMatchCandidate {
id,
char_bag: name.as_str().into(), char_bag: name.as_str().into(),
string: name, string: name,
}) })
@ -169,7 +171,7 @@ impl ThemeSelector {
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(index, candidate)| StringMatch { .map(|(index, candidate)| StringMatch {
candidate_index: index, candidate_id: index,
string: candidate.string, string: candidate.string,
positions: Vec::new(), positions: Vec::new(),
score: 0.0, score: 0.0,