Match full path when query contains spaces

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Nathan Sobo 2022-01-14 09:02:04 -07:00
parent be24e58926
commit f934370e7f

View file

@ -6,6 +6,8 @@ use std::{ops::Range, sync::Arc};
pub struct Outline<T> { pub struct Outline<T> {
pub items: Vec<OutlineItem<T>>, pub items: Vec<OutlineItem<T>>,
candidates: Vec<StringMatchCandidate>, candidates: Vec<StringMatchCandidate>,
path_candidates: Vec<StringMatchCandidate>,
path_candidate_prefixes: Vec<usize>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -18,6 +20,30 @@ pub struct OutlineItem<T> {
impl<T> Outline<T> { impl<T> Outline<T> {
pub fn new(items: Vec<OutlineItem<T>>) -> Self { pub fn new(items: Vec<OutlineItem<T>>) -> Self {
let mut path_candidates = Vec::new();
let mut path_candidate_prefixes = Vec::new();
let mut item_text = String::new();
let mut stack = Vec::new();
for (id, item) in items.iter().enumerate() {
if item.depth < stack.len() {
stack.truncate(item.depth);
item_text.truncate(stack.last().copied().unwrap_or(0));
}
if !item_text.is_empty() {
item_text.push(' ');
}
path_candidate_prefixes.push(item_text.len());
item_text.push_str(&item.text);
stack.push(item_text.len());
path_candidates.push(StringMatchCandidate {
id,
string: item_text.clone(),
char_bag: item_text.as_str().into(),
});
}
Self { Self {
candidates: items candidates: items
.iter() .iter()
@ -28,13 +54,21 @@ impl<T> Outline<T> {
string: item.text.clone(), string: item.text.clone(),
}) })
.collect(), .collect(),
path_candidates,
path_candidate_prefixes,
items, items,
} }
} }
pub async fn search(&self, query: &str, executor: Arc<Background>) -> Vec<StringMatch> { pub async fn search(&self, query: &str, executor: Arc<Background>) -> Vec<StringMatch> {
let query = query.trim_start();
let is_path_query = query.contains(' ');
let mut matches = fuzzy::match_strings( let mut matches = fuzzy::match_strings(
&self.candidates, if is_path_query {
&self.path_candidates
} else {
&self.candidates
},
query, query,
true, true,
100, 100,
@ -47,8 +81,19 @@ impl<T> Outline<T> {
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 mut string_match in matches {
let outline_match = &self.items[string_match.candidate_id]; let outline_match = &self.items[string_match.candidate_id];
if is_path_query {
let prefix_len = self.path_candidate_prefixes[string_match.candidate_id];
string_match
.positions
.retain(|position| *position >= prefix_len);
for position in &mut string_match.positions {
*position -= prefix_len;
}
}
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_id] for (ix, item) in self.items[prev_item_ix..string_match.candidate_id]