search: Improve performance of replace_all
(#13654)
Previously replace_all amounted to what could be achieved by repeatedly mashing "Replace" button, which had a bunch of overhead related to buffer state syncing. This commit gets rid of the automated button mashing, processing all of the replacements in one go. Fixes #13455 Release Notes: - Improved performance of "replace all" in buffer search and project search
This commit is contained in:
parent
b616f9c27f
commit
0761383752
4 changed files with 58 additions and 6 deletions
|
@ -1102,6 +1102,35 @@ impl SearchableItem for Editor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn replace_all(
|
||||||
|
&mut self,
|
||||||
|
matches: &mut dyn Iterator<Item = &Self::Match>,
|
||||||
|
query: &SearchQuery,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
let text = self.buffer.read(cx);
|
||||||
|
let text = text.snapshot(cx);
|
||||||
|
let mut edits = vec![];
|
||||||
|
for m in matches {
|
||||||
|
let text = text.text_for_range(m.clone()).collect::<Vec<_>>();
|
||||||
|
let text: Cow<_> = if text.len() == 1 {
|
||||||
|
text.first().cloned().unwrap().into()
|
||||||
|
} else {
|
||||||
|
let joined_chunks = text.join("");
|
||||||
|
joined_chunks.into()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(replacement) = query.replacement_for(&text) {
|
||||||
|
edits.push((m.clone(), Arc::from(&*replacement)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !edits.is_empty() {
|
||||||
|
self.transact(cx, |this, cx| {
|
||||||
|
this.edit(edits, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
fn match_index_for_direction(
|
fn match_index_for_direction(
|
||||||
&mut self,
|
&mut self,
|
||||||
matches: &[Range<Anchor>],
|
matches: &[Range<Anchor>],
|
||||||
|
|
|
@ -1122,9 +1122,7 @@ impl BufferSearchBar {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.clone()
|
.clone()
|
||||||
.with_replacement(self.replacement(cx));
|
.with_replacement(self.replacement(cx));
|
||||||
for m in matches {
|
searchable_item.replace_all(&mut matches.iter(), &query, cx);
|
||||||
searchable_item.replace(m, &query, cx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,9 +591,7 @@ impl ProjectSearchView {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.results_editor.update(cx, |editor, cx| {
|
self.results_editor.update(cx, |editor, cx| {
|
||||||
for item in &match_ranges {
|
editor.replace_all(&mut match_ranges.iter(), &query, cx);
|
||||||
editor.replace(item, &query, cx);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.model.update(cx, |model, _cx| {
|
self.model.update(cx, |model, _cx| {
|
||||||
|
|
|
@ -71,6 +71,16 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
|
||||||
fn activate_match(&mut self, index: usize, matches: &[Self::Match], cx: &mut ViewContext<Self>);
|
fn activate_match(&mut self, index: usize, matches: &[Self::Match], cx: &mut ViewContext<Self>);
|
||||||
fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>);
|
fn select_matches(&mut self, matches: &[Self::Match], cx: &mut ViewContext<Self>);
|
||||||
fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>);
|
fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>);
|
||||||
|
fn replace_all(
|
||||||
|
&mut self,
|
||||||
|
matches: &mut dyn Iterator<Item = &Self::Match>,
|
||||||
|
query: &SearchQuery,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
for item in matches {
|
||||||
|
self.replace(item, query, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn match_index_for_direction(
|
fn match_index_for_direction(
|
||||||
&mut self,
|
&mut self,
|
||||||
matches: &[Self::Match],
|
matches: &[Self::Match],
|
||||||
|
@ -123,6 +133,12 @@ pub trait SearchableItemHandle: ItemHandle {
|
||||||
_: &SearchQuery,
|
_: &SearchQuery,
|
||||||
_: &mut WindowContext,
|
_: &mut WindowContext,
|
||||||
);
|
);
|
||||||
|
fn replace_all(
|
||||||
|
&self,
|
||||||
|
matches: &mut dyn Iterator<Item = any_vec::element::ElementRef<'_, dyn Send>>,
|
||||||
|
query: &SearchQuery,
|
||||||
|
cx: &mut WindowContext,
|
||||||
|
);
|
||||||
fn match_index_for_direction(
|
fn match_index_for_direction(
|
||||||
&self,
|
&self,
|
||||||
matches: &AnyVec<dyn Send>,
|
matches: &AnyVec<dyn Send>,
|
||||||
|
@ -241,6 +257,17 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
|
||||||
self.update(cx, |this, cx| this.replace(mat, query, cx))
|
self.update(cx, |this, cx| this.replace(mat, query, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn replace_all(
|
||||||
|
&self,
|
||||||
|
matches: &mut dyn Iterator<Item = any_vec::element::ElementRef<'_, dyn Send>>,
|
||||||
|
query: &SearchQuery,
|
||||||
|
cx: &mut WindowContext,
|
||||||
|
) {
|
||||||
|
self.update(cx, |this, cx| {
|
||||||
|
this.replace_all(&mut matches.map(|m| m.downcast_ref().unwrap()), query, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn search_bar_visibility_changed(&self, visible: bool, cx: &mut WindowContext) {
|
fn search_bar_visibility_changed(&self, visible: bool, cx: &mut WindowContext) {
|
||||||
self.update(cx, |this, cx| {
|
self.update(cx, |this, cx| {
|
||||||
this.search_bar_visibility_changed(visible, cx)
|
this.search_bar_visibility_changed(visible, cx)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue