Maintain search results as query and active editor changes

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-01-28 15:19:58 +01:00
parent 860e37d50f
commit 5c862bfe98
4 changed files with 69 additions and 8 deletions

1
Cargo.lock generated
View file

@ -1724,6 +1724,7 @@ name = "find"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"collections",
"editor", "editor",
"gpui", "gpui",
"postage", "postage",

View file

@ -7,10 +7,11 @@ edition = "2021"
path = "src/find.rs" path = "src/find.rs"
[dependencies] [dependencies]
aho-corasick = "0.7" collections = { path = "../collections" }
editor = { path = "../editor" } editor = { path = "../editor" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
theme = { path = "../theme" } theme = { path = "../theme" }
workspace = { path = "../workspace" } workspace = { path = "../workspace" }
aho-corasick = "0.7"
postage = { version = "0.4.1", features = ["futures-traits"] } postage = { version = "0.4.1", features = ["futures-traits"] }
smol = { version = "1.2" } smol = { version = "1.2" }

View file

@ -1,8 +1,9 @@
use aho_corasick::AhoCorasickBuilder; use aho_corasick::AhoCorasickBuilder;
use collections::HashSet;
use editor::{char_kind, Editor, EditorSettings}; use editor::{char_kind, Editor, EditorSettings};
use gpui::{ use gpui::{
action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, Task, View, action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, Subscription,
ViewContext, ViewHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle,
}; };
use postage::watch; use postage::watch;
use smol::future::yield_now; use smol::future::yield_now;
@ -34,6 +35,8 @@ struct FindBar {
settings: watch::Receiver<Settings>, settings: watch::Receiver<Settings>,
query_editor: ViewHandle<Editor>, query_editor: ViewHandle<Editor>,
active_editor: Option<ViewHandle<Editor>>, active_editor: Option<ViewHandle<Editor>>,
active_editor_subscription: Option<Subscription>,
highlighted_editors: HashSet<WeakViewHandle<Editor>>,
pending_search: Option<Task<()>>, pending_search: Option<Task<()>>,
case_sensitive_mode: bool, case_sensitive_mode: bool,
whole_word_mode: bool, whole_word_mode: bool,
@ -85,8 +88,19 @@ impl Toolbar for FindBar {
item: Option<Box<dyn ItemViewHandle>>, item: Option<Box<dyn ItemViewHandle>>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> bool { ) -> bool {
self.active_editor = item.and_then(|item| item.act_as::<Editor>(cx)); self.active_editor_subscription.take();
self.active_editor.is_some() self.active_editor.take();
self.pending_search.take();
if let Some(editor) = item.and_then(|item| item.act_as::<Editor>(cx)) {
self.active_editor_subscription =
Some(cx.subscribe(&editor, Self::on_active_editor_event));
self.active_editor = Some(editor);
self.update_matches(cx);
true
} else {
false
}
} }
} }
@ -114,6 +128,8 @@ impl FindBar {
Self { Self {
query_editor, query_editor,
active_editor: None, active_editor: None,
active_editor_subscription: None,
highlighted_editors: Default::default(),
case_sensitive_mode: false, case_sensitive_mode: false,
whole_word_mode: false, whole_word_mode: false,
regex_mode: false, regex_mode: false,
@ -171,23 +187,49 @@ impl FindBar {
} }
fn toggle_mode(&mut self, ToggleMode(mode): &ToggleMode, cx: &mut ViewContext<Self>) { fn toggle_mode(&mut self, ToggleMode(mode): &ToggleMode, cx: &mut ViewContext<Self>) {
eprintln!("TOGGLE MODE");
let value = match mode { let value = match mode {
SearchMode::WholeWord => &mut self.whole_word_mode, SearchMode::WholeWord => &mut self.whole_word_mode,
SearchMode::CaseSensitive => &mut self.case_sensitive_mode, SearchMode::CaseSensitive => &mut self.case_sensitive_mode,
SearchMode::Regex => &mut self.regex_mode, SearchMode::Regex => &mut self.regex_mode,
}; };
*value = !*value; *value = !*value;
self.update_matches(cx);
cx.notify(); cx.notify();
} }
fn on_query_editor_event( fn on_query_editor_event(
&mut self, &mut self,
_: ViewHandle<Editor>, _: ViewHandle<Editor>,
_: &editor::Event, event: &editor::Event,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
self.update_matches(cx); match event {
editor::Event::Edited => {
for editor in self.highlighted_editors.drain() {
if let Some(editor) = editor.upgrade(cx) {
if Some(&editor) != self.active_editor.as_ref() {
editor.update(cx, |editor, cx| {
editor.clear_highlighted_ranges::<Self>(cx)
});
}
}
}
self.update_matches(cx);
}
_ => {}
}
}
fn on_active_editor_event(
&mut self,
_: ViewHandle<Editor>,
event: &editor::Event,
cx: &mut ViewContext<Self>,
) {
match event {
editor::Event::Edited => self.update_matches(cx),
_ => {}
}
} }
fn update_matches(&mut self, cx: &mut ViewContext<Self>) { fn update_matches(&mut self, cx: &mut ViewContext<Self>) {
@ -247,6 +289,7 @@ impl FindBar {
{ {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
let theme = &this.settings.borrow().theme.find; let theme = &this.settings.borrow().theme.find;
this.highlighted_editors.insert(editor.downgrade());
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
editor.highlight_ranges::<Self>(ranges, theme.match_background, cx) editor.highlight_ranges::<Self>(ranges, theme.match_background, cx)
}); });

View file

@ -3246,6 +3246,7 @@ impl Drop for AnyModelHandle {
self.ref_counts.lock().dec_model(self.model_id); self.ref_counts.lock().dec_model(self.model_id);
} }
} }
pub struct WeakViewHandle<T> { pub struct WeakViewHandle<T> {
window_id: usize, window_id: usize,
view_id: usize, view_id: usize,
@ -3288,6 +3289,21 @@ impl<T> Clone for WeakViewHandle<T> {
} }
} }
impl<T> PartialEq for WeakViewHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.window_id == other.window_id && self.view_id == other.view_id
}
}
impl<T> Eq for WeakViewHandle<T> {}
impl<T> Hash for WeakViewHandle<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.window_id.hash(state);
self.view_id.hash(state);
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementStateId(usize, usize); pub struct ElementStateId(usize, usize);