Allow going to next/prev match even if `FindBar` has been dismissed

Antonio Scandurra created

Change summary

crates/find/src/find.rs | 52 +++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 23 deletions(-)

Detailed changes

crates/find/src/find.rs 🔗

@@ -1,6 +1,6 @@
 use aho_corasick::AhoCorasickBuilder;
 use anyhow::Result;
-use collections::HashSet;
+use collections::HashMap;
 use editor::{
     char_kind, display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor, EditorSettings,
     MultiBufferSnapshot,
@@ -63,12 +63,13 @@ struct FindBar {
     active_editor: Option<ViewHandle<Editor>>,
     active_match_index: Option<usize>,
     active_editor_subscription: Option<Subscription>,
-    highlighted_editors: HashSet<WeakViewHandle<Editor>>,
+    editors_with_matches: HashMap<WeakViewHandle<Editor>, Vec<Range<Anchor>>>,
     pending_search: Option<Task<()>>,
     case_sensitive_mode: bool,
     whole_word_mode: bool,
     regex_mode: bool,
     query_contains_error: bool,
+    dismissed: bool,
 }
 
 impl Entity for FindBar {
@@ -119,10 +120,9 @@ impl View for FindBar {
                     .boxed(),
             )
             .with_children(self.active_editor.as_ref().and_then(|editor| {
-                let (_, highlighted_ranges) =
-                    editor.read(cx).highlighted_ranges_for_type::<Self>()?;
+                let matches = self.editors_with_matches.get(&editor.downgrade())?;
                 let message = if let Some(match_ix) = self.active_match_index {
-                    format!("{}/{}", match_ix + 1, highlighted_ranges.len())
+                    format!("{}/{}", match_ix + 1, matches.len())
                 } else {
                     "No matches".to_string()
                 };
@@ -165,11 +165,12 @@ impl Toolbar for FindBar {
     }
 
     fn on_dismiss(&mut self, cx: &mut ViewContext<Self>) {
-        self.active_editor.take();
-        self.active_editor_subscription.take();
-        self.active_match_index.take();
-        self.pending_search.take();
-        self.clear_matches(cx);
+        self.dismissed = true;
+        for (editor, _) in &self.editors_with_matches {
+            if let Some(editor) = editor.upgrade(cx) {
+                editor.update(cx, |editor, cx| editor.clear_highlighted_ranges::<Self>(cx));
+            }
+        }
     }
 }
 
@@ -200,13 +201,14 @@ impl FindBar {
             active_editor: None,
             active_editor_subscription: None,
             active_match_index: None,
-            highlighted_editors: Default::default(),
+            editors_with_matches: Default::default(),
             case_sensitive_mode: false,
             whole_word_mode: false,
             regex_mode: false,
             settings,
             pending_search: None,
             query_contains_error: false,
+            dismissed: false,
         }
     }
 
@@ -277,6 +279,7 @@ impl FindBar {
                 .active_toolbar()
                 .and_then(|toolbar| toolbar.downcast::<Self>())
             {
+                find_bar.update(cx, |find_bar, _| find_bar.dismissed = false);
                 let editor = pane.active_item().unwrap().act_as::<Editor>(cx).unwrap();
                 let display_map = editor
                     .update(cx, |editor, cx| editor.snapshot(cx))
@@ -353,7 +356,7 @@ impl FindBar {
             if let Some(editor) = self.active_editor.as_ref() {
                 editor.update(cx, |editor, cx| {
                     let newest_selection = editor.newest_anchor_selection().clone();
-                    if let Some((_, ranges)) = editor.highlighted_ranges_for_type::<Self>() {
+                    if let Some(ranges) = self.editors_with_matches.get(&cx.weak_handle()) {
                         let position = newest_selection.head();
                         let buffer = editor.buffer().read(cx).read(cx);
                         if ranges[index].start.cmp(&position, &buffer).unwrap().is_gt() {
@@ -428,7 +431,7 @@ impl FindBar {
     }
 
     fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
-        for editor in self.highlighted_editors.drain() {
+        for (editor, _) in self.editors_with_matches.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));
@@ -463,15 +466,18 @@ impl FindBar {
                         Ok(ranges) => {
                             if let Some(editor) = editor.upgrade(&cx) {
                                 this.update(&mut cx, |this, cx| {
-                                    this.highlighted_editors.insert(editor.downgrade());
-                                    editor.update(cx, |editor, cx| {
-                                        let theme = &this.settings.borrow().theme.find;
-                                        editor.highlight_ranges::<Self>(
-                                            ranges,
-                                            theme.match_background,
-                                            cx,
-                                        )
-                                    });
+                                    this.editors_with_matches
+                                        .insert(editor.downgrade(), ranges.clone());
+                                    if !this.dismissed {
+                                        editor.update(cx, |editor, cx| {
+                                            let theme = &this.settings.borrow().theme.find;
+                                            editor.highlight_ranges::<Self>(
+                                                ranges,
+                                                theme.match_background,
+                                                cx,
+                                            )
+                                        });
+                                    }
                                     this.update_match_index(cx);
                                 });
                             }
@@ -495,9 +501,9 @@ impl FindBar {
 
     fn active_match_index(&mut self, cx: &mut ViewContext<Self>) -> Option<usize> {
         let editor = self.active_editor.as_ref()?;
+        let ranges = self.editors_with_matches.get(&editor.downgrade())?;
         let editor = editor.read(cx);
         let position = editor.newest_anchor_selection().head();
-        let ranges = editor.highlighted_ranges_for_type::<Self>()?.1;
         if ranges.is_empty() {
             None
         } else {