Terminal implements important half of search protocol

Mikayla Maki created

Change summary

assets/keymaps/default.json                    |   3 
crates/editor/src/items.rs                     |  14 
crates/search/src/buffer_search.rs             |  10 
crates/terminal/src/terminal.rs                | 167 +++++++++++--------
crates/terminal/src/terminal_container_view.rs |  99 +++++++++++
crates/terminal/src/terminal_element.rs        |  17 +
crates/terminal/src/terminal_view.rs           |  31 ++-
crates/workspace/src/searchable.rs             |  29 +-
8 files changed, 250 insertions(+), 120 deletions(-)

Detailed changes

assets/keymaps/default.json 🔗

@@ -424,8 +424,7 @@
             "ctrl-cmd-space": "terminal::ShowCharacterPalette",
             "cmd-c": "terminal::Copy",
             "cmd-v": "terminal::Paste",
-            "cmd-k": "terminal::Clear",
-            "cmd-s": "terminal::SearchTest"
+            "cmd-k": "terminal::Clear"
         }
     },
     {

crates/editor/src/items.rs 🔗

@@ -513,17 +513,17 @@ impl SearchableItem for Editor {
 
     fn to_search_event(event: &Self::Event) -> Option<SearchEvent> {
         match event {
-            Event::BufferEdited => Some(SearchEvent::ContentsUpdated),
-            Event::SelectionsChanged { .. } => Some(SearchEvent::SelectionsChanged),
+            Event::BufferEdited => Some(SearchEvent::MatchesInvalidated),
+            Event::SelectionsChanged { .. } => Some(SearchEvent::ActiveMatchChanged),
             _ => None,
         }
     }
 
-    fn clear_highlights(&mut self, cx: &mut ViewContext<Self>) {
+    fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
         self.clear_background_highlights::<BufferSearchHighlights>(cx);
     }
 
-    fn highlight_matches(&mut self, matches: Vec<Range<Anchor>>, cx: &mut ViewContext<Self>) {
+    fn update_matches(&mut self, matches: Vec<Range<Anchor>>, cx: &mut ViewContext<Self>) {
         self.highlight_background::<BufferSearchHighlights>(
             matches,
             |theme| theme.search.match_background,
@@ -553,7 +553,7 @@ impl SearchableItem for Editor {
         }
     }
 
-    fn select_next_match_in_direction(
+    fn activate_next_match(
         &mut self,
         index: usize,
         direction: Direction,
@@ -575,7 +575,7 @@ impl SearchableItem for Editor {
         });
     }
 
-    fn select_match_by_index(
+    fn activate_match_at_index(
         &mut self,
         index: usize,
         matches: Vec<Range<Anchor>>,
@@ -586,7 +586,7 @@ impl SearchableItem for Editor {
         });
     }
 
-    fn matches(
+    fn find_matches(
         &mut self,
         query: project::search::SearchQuery,
         cx: &mut ViewContext<Self>,

crates/search/src/buffer_search.rs 🔗

@@ -174,7 +174,9 @@ impl ToolbarItemView for BufferSearchBar {
                 cx,
                 Box::new(move |search_event, cx| {
                     if let Some(this) = handle.upgrade(cx) {
-                        this.update(cx, |this, cx| this.on_active_editor_event(search_event, cx));
+                        this.update(cx, |this, cx| {
+                            this.on_active_searchable_item_event(search_event, cx)
+                        });
                     }
                 }),
             ));
@@ -461,10 +463,10 @@ impl BufferSearchBar {
         }
     }
 
-    fn on_active_editor_event(&mut self, event: SearchEvent, cx: &mut ViewContext<Self>) {
+    fn on_active_searchable_item_event(&mut self, event: SearchEvent, cx: &mut ViewContext<Self>) {
         match event {
-            SearchEvent::ContentsUpdated => self.update_matches(false, cx),
-            SearchEvent::SelectionsChanged => self.update_match_index(cx),
+            SearchEvent::MatchesInvalidated => self.update_matches(false, cx),
+            SearchEvent::ActiveMatchChanged => self.update_match_index(cx),
         }
     }
 

crates/terminal/src/terminal.rs 🔗

@@ -36,7 +36,7 @@ use settings::{AlternateScroll, Settings, Shell, TerminalBlink};
 use std::{
     collections::{HashMap, VecDeque},
     fmt::Display,
-    ops::Sub,
+    ops::{RangeInclusive, Sub},
     path::PathBuf,
     sync::Arc,
     time::Duration,
@@ -48,7 +48,7 @@ use gpui::{
     keymap::Keystroke,
     scene::{ClickRegionEvent, DownRegionEvent, DragRegionEvent, UpRegionEvent},
     ClipboardItem, Entity, ModelContext, MouseButton, MouseMovedEvent, MutableAppContext,
-    ScrollWheelEvent,
+    ScrollWheelEvent, Task,
 };
 
 use crate::mappings::{
@@ -68,8 +68,6 @@ pub fn init(cx: &mut MutableAppContext) {
 ///Scroll multiplier that is set to 3 by default. This will be removed when I
 ///Implement scroll bars.
 const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
-// const ALACRITTY_SEARCH_LINE_LIMIT: usize = 1000;
-const SEARCH_FORWARD: Direction = Direction::Left;
 const MAX_SEARCH_LINES: usize = 100;
 const DEBUG_TERMINAL_WIDTH: f32 = 500.;
 const DEBUG_TERMINAL_HEIGHT: f32 = 30.;
@@ -91,7 +89,7 @@ enum InternalEvent {
     ColorRequest(usize, Arc<dyn Fn(Rgb) -> String + Sync + Send + 'static>),
     Resize(TerminalSize),
     Clear,
-    FocusNextMatch,
+    // FocusNextMatch,
     Scroll(AlacScroll),
     SetSelection(Option<Selection>),
     UpdateSelection(Vector2F),
@@ -382,7 +380,8 @@ impl TerminalBuilder {
             cur_size: initial_size,
             last_mouse: None,
             last_offset: 0,
-            searcher: None,
+            matches: Vec::new(),
+            selection_text: None,
         };
 
         Ok(TerminalBuilder {
@@ -454,7 +453,8 @@ pub struct Terminal {
     last_mode: TermMode,
     last_offset: usize,
     last_mouse: Option<(Point, Direction)>,
-    searcher: Option<(Option<RegexSearch>, Point)>,
+    pub matches: Vec<RangeInclusive<Point>>,
+    pub selection_text: Option<String>,
 }
 
 impl Terminal {
@@ -531,32 +531,32 @@ impl Terminal {
             InternalEvent::Scroll(scroll) => {
                 term.scroll_display(*scroll);
             }
-            InternalEvent::FocusNextMatch => {
-                if let Some((Some(searcher), _origin)) = &self.searcher {
-                    match term.search_next(
-                        searcher,
-                        Point {
-                            line: Line(0),
-                            column: Column(0),
-                        },
-                        SEARCH_FORWARD,
-                        Direction::Left,
-                        None,
-                    ) {
-                        Some(regex_match) => {
-                            term.scroll_to_point(*regex_match.start());
-
-                            //Focus is done with selections in zed
-                            let focus = make_selection(*regex_match.start(), *regex_match.end());
-                            term.selection = Some(focus);
-                        }
-                        None => {
-                            //Clear focused match
-                            term.selection = None;
-                        }
-                    }
-                }
-            }
+            // InternalEvent::FocusNextMatch => {
+            //     if let Some((Some(searcher), _origin)) = &self.searcher {
+            //         match term.search_next(
+            //             searcher,
+            //             Point {
+            //                 line: Line(0),
+            //                 column: Column(0),
+            //             },
+            //             SEARCH_FORWARD,
+            //             Direction::Left,
+            //             None,
+            //         ) {
+            //             Some(regex_match) => {
+            //                 term.scroll_to_point(*regex_match.start());
+
+            //                 //Focus is done with selections in zed
+            //                 let focus = make_selection(*regex_match.start(), *regex_match.end());
+            //                 term.selection = Some(focus);
+            //             }
+            //             None => {
+            //                 //Clear focused match
+            //                 term.selection = None;
+            //             }
+            //         }
+            //     }
+            // }
             InternalEvent::SetSelection(sel) => term.selection = sel.clone(),
             InternalEvent::UpdateSelection(position) => {
                 if let Some(mut selection) = term.selection.take() {
@@ -594,34 +594,34 @@ impl Terminal {
         self.events.push_back(InternalEvent::Scroll(scroll));
     }
 
-    fn focus_next_match(&mut self) {
-        self.events.push_back(InternalEvent::FocusNextMatch);
-    }
+    // fn focus_next_match(&mut self) {
+    //     self.events.push_back(InternalEvent::FocusNextMatch);
+    // }
 
-    pub fn search(&mut self, search: &str) {
-        let new_searcher = RegexSearch::new(search).ok();
-        self.searcher = match (new_searcher, &self.searcher) {
-            //Nothing to do :(
-            (None, None) => None,
-            //No existing search, start a new one
-            (Some(new_searcher), None) => Some((Some(new_searcher), self.viewport_origin())),
-            //Existing search, carry over origin
-            (new_searcher, Some((_, origin))) => Some((new_searcher, *origin)),
-        };
+    // pub fn search(&mut self, search: &str) {
+    //     let new_searcher = RegexSearch::new(search).ok();
+    //     self.searcher = match (new_searcher, &self.searcher) {
+    //         //Nothing to do :(
+    //         (None, None) => None,
+    //         //No existing search, start a new one
+    //         (Some(new_searcher), None) => Some((Some(new_searcher), self.viewport_origin())),
+    //         //Existing search, carry over origin
+    //         (new_searcher, Some((_, origin))) => Some((new_searcher, *origin)),
+    //     };
 
-        if let Some((Some(_), _)) = self.searcher {
-            self.focus_next_match();
-        }
-    }
+    //     if let Some((Some(_), _)) = self.searcher {
+    //         self.focus_next_match();
+    //     }
+    // }
 
-    fn viewport_origin(&mut self) -> Point {
-        let viewport_top = alacritty_terminal::index::Line(-(self.last_offset as i32)) - 1;
-        Point::new(viewport_top, alacritty_terminal::index::Column(0))
-    }
+    // fn viewport_origin(&mut self) -> Point {
+    //     let viewport_top = alacritty_terminal::index::Line(-(self.last_offset as i32)) - 1;
+    //     Point::new(viewport_top, alacritty_terminal::index::Column(0))
+    // }
 
-    pub fn end_search(&mut self) {
-        self.searcher = None;
-    }
+    // pub fn end_search(&mut self) {
+    //     self.searcher = None;
+    // }
 
     pub fn copy(&mut self) {
         self.events.push_back(InternalEvent::Copy);
@@ -669,12 +669,12 @@ impl Terminal {
 
     pub fn render_lock<F, T>(&mut self, cx: &mut ModelContext<Self>, f: F) -> T
     where
-        F: FnOnce(RenderableContent, char, Vec<Match>) -> T,
+        F: FnOnce(RenderableContent, char) -> T,
     {
-        let m = self.term.clone(); //Arc clone
-        let mut term = m.lock();
+        let term = self.term.clone();
+        let mut term = term.lock();
 
-        //Note that this ordering matters for
+        //Note that this ordering matters for event processing
         while let Some(e) = self.events.pop_front() {
             self.process_terminal_event(&e, &mut term, cx)
         }
@@ -683,16 +683,12 @@ impl Terminal {
 
         let content = term.renderable_content();
 
+        self.selection_text = term.selection_to_string();
         self.last_offset = content.display_offset;
 
         let cursor_text = term.grid()[content.cursor.point].c;
 
-        let mut matches = vec![];
-        if let Some((Some(r), _)) = &self.searcher {
-            matches.extend(make_search_matches(&term, &r));
-        }
-
-        f(content, cursor_text, matches)
+        f(content, cursor_text)
     }
 
     pub fn focus_in(&self) {
@@ -865,6 +861,33 @@ impl Terminal {
             }
         }
     }
+
+    pub fn find_matches(
+        &mut self,
+        query: project::search::SearchQuery,
+        cx: &mut ModelContext<Self>,
+    ) -> Task<Vec<RangeInclusive<Point>>> {
+        let term = self.term.clone();
+        dbg!("Spawning find_matches");
+        cx.background().spawn(async move {
+            let searcher = match query {
+                project::search::SearchQuery::Text { query, .. } => {
+                    RegexSearch::new(query.as_ref())
+                }
+                project::search::SearchQuery::Regex { query, .. } => {
+                    RegexSearch::new(query.as_ref())
+                }
+            };
+
+            if searcher.is_err() {
+                return Vec::new();
+            }
+            let searcher = searcher.unwrap();
+
+            let term = term.lock();
+            dbg!(make_search_matches(&term, &searcher).collect())
+        })
+    }
 }
 
 impl Drop for Terminal {
@@ -877,11 +900,11 @@ impl Entity for Terminal {
     type Event = Event;
 }
 
-fn make_selection(from: Point, to: Point) -> Selection {
-    let mut focus = Selection::new(SelectionType::Simple, from, Direction::Left);
-    focus.update(to, Direction::Right);
-    focus
-}
+// fn make_selection(from: Point, to: Point) -> Selection {
+//     let mut focus = Selection::new(SelectionType::Simple, from, Direction::Left);
+//     focus.update(to, Direction::Right);
+//     focus
+// }
 
 /// Copied from alacritty/src/display/hint.rs HintMatches::visible_regex_matches()
 /// Iterate over all visible regex matches.

crates/terminal/src/terminal_container_view.rs 🔗

@@ -1,17 +1,20 @@
 use crate::terminal_view::TerminalView;
 use crate::{Event, Terminal, TerminalBuilder, TerminalError};
 
+use alacritty_terminal::index::Point;
 use dirs::home_dir;
 use gpui::{
-    actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, View,
-    ViewContext, ViewHandle,
+    actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, Task,
+    View, ViewContext, ViewHandle,
 };
+use workspace::searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle};
 use workspace::{Item, Workspace};
 
 use crate::TerminalSize;
 use project::{LocalWorktree, Project, ProjectPath};
 use settings::{AlternateScroll, Settings, WorkingDirectory};
 use smallvec::SmallVec;
+use std::ops::RangeInclusive;
 use std::path::{Path, PathBuf};
 
 use crate::terminal_element::TerminalElement;
@@ -328,6 +331,98 @@ impl Item for TerminalContainer {
     fn should_close_item_on_event(event: &Self::Event) -> bool {
         matches!(event, &Event::CloseTerminal)
     }
+
+    fn as_searchable(&self, handle: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
+        Some(Box::new(handle.clone()))
+    }
+}
+
+impl SearchableItem for TerminalContainer {
+    type Match = RangeInclusive<Point>;
+
+    /// Convert events raised by this item into search-relevant events (if applicable)
+    fn to_search_event(event: &Self::Event) -> Option<SearchEvent> {
+        match event {
+            Event::Wakeup => Some(SearchEvent::MatchesInvalidated),
+            //TODO selection changed
+            _ => None,
+        }
+    }
+
+    /// Clear stored matches
+    fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
+        if let TerminalContent::Connected(connected) = &self.content {
+            let terminal = connected.read(cx).terminal().clone();
+            terminal.update(cx, |term, _| term.matches.clear())
+        }
+    }
+
+    /// Store matches returned from find_matches somewhere for rendering
+    fn update_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>) {
+        if let TerminalContent::Connected(connected) = &self.content {
+            let terminal = connected.read(cx).terminal().clone();
+            dbg!(&matches);
+            terminal.update(cx, |term, _| term.matches = matches)
+        }
+    }
+
+    /// Return the selection content to pre-load into this search
+    fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
+        if let TerminalContent::Connected(connected) = &self.content {
+            let terminal = connected.read(cx).terminal().clone();
+            terminal.read(cx).selection_text.clone().unwrap_or_default()
+        } else {
+            Default::default()
+        }
+    }
+
+    /// Given an index, a set of matches for this index, and a direction,
+    /// get the next match (clicking the arrow)
+    fn activate_next_match(
+        &mut self,
+        _index: usize,
+        _direction: Direction,
+        _matches: Vec<Self::Match>,
+        _cx: &mut ViewContext<Self>,
+    ) {
+        // TODO:
+    }
+
+    /// Focus match at given index into the Vec of matches
+    fn activate_match_at_index(
+        &mut self,
+        _index: usize,
+        _matches: Vec<Self::Match>,
+        _cx: &mut ViewContext<Self>,
+    ) {
+    }
+
+    /// Get all of the matches for this query, should be done on the background
+    fn find_matches(
+        &mut self,
+        query: project::search::SearchQuery,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<Vec<Self::Match>> {
+        if let TerminalContent::Connected(connected) = &self.content {
+            let terminal = connected.read(cx).terminal().clone();
+            terminal.update(cx, |term, cx| term.find_matches(query, cx))
+        } else {
+            Task::ready(Vec::new())
+        }
+    }
+
+    /// Reports back to the search toolbar what the active match should be (the selection)
+    fn active_match_index(
+        &mut self,
+        matches: Vec<Self::Match>,
+        _cx: &mut ViewContext<Self>,
+    ) -> Option<usize> {
+        if matches.len() > 0 {
+            Some(0)
+        } else {
+            None
+        }
+    }
 }
 
 ///Get's the working directory for the given workspace, respecting the user's settings.

crates/terminal/src/terminal_element.rs 🔗

@@ -570,19 +570,25 @@ impl Element for TerminalElement {
             TerminalSize::new(line_height, cell_width, constraint.max)
         };
 
+        let search_matches = if let Some(terminal_model) = self.terminal.upgrade(cx) {
+            terminal_model.read(cx).matches.clone()
+        } else {
+            Default::default()
+        };
+
         let background_color = if self.modal {
             terminal_theme.colors.modal_background
         } else {
             terminal_theme.colors.background
         };
 
-        let (cells, selection, cursor, display_offset, cursor_text, search_matches, mode) = self
+        let (cells, selection, cursor, display_offset, cursor_text, mode) = self
             .terminal
             .upgrade(cx)
             .unwrap()
             .update(cx.app, |terminal, cx| {
                 terminal.set_size(dimensions);
-                terminal.render_lock(cx, |content, cursor_text, search_matches| {
+                terminal.render_lock(cx, |content, cursor_text| {
                     let mut cells = vec![];
                     cells.extend(
                         content
@@ -605,7 +611,6 @@ impl Element for TerminalElement {
                         content.cursor,
                         content.display_offset,
                         cursor_text,
-                        search_matches.clone(),
                         content.mode,
                     )
                 })
@@ -613,12 +618,12 @@ impl Element for TerminalElement {
 
         // searches, highlights to a single range representations
         let mut relative_highlighted_ranges = Vec::new();
-        if let Some(selection) = selection {
-            relative_highlighted_ranges.push((selection.start..=selection.end, selection_color));
-        }
         for search_match in search_matches {
             relative_highlighted_ranges.push((search_match, match_color))
         }
+        if let Some(selection) = selection {
+            relative_highlighted_ranges.push((selection.start..=selection.end, selection_color));
+        }
 
         // then have that representation be converted to the appropriate highlight data structure
 

crates/terminal/src/terminal_view.rs 🔗

@@ -1,6 +1,6 @@
-use std::time::Duration;
+use std::{ops::RangeInclusive, time::Duration};
 
-use alacritty_terminal::term::TermMode;
+use alacritty_terminal::{index::Point, term::TermMode};
 use context_menu::{ContextMenu, ContextMenuItem};
 use gpui::{
     actions,
@@ -8,8 +8,8 @@ use gpui::{
     geometry::vector::Vector2F,
     impl_internal_actions,
     keymap::Keystroke,
-    AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View,
-    ViewContext, ViewHandle,
+    AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, Task,
+    View, ViewContext, ViewHandle,
 };
 use settings::{Settings, TerminalBlink};
 use smol::Timer;
@@ -58,8 +58,6 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(TerminalView::paste);
     cx.add_action(TerminalView::clear);
     cx.add_action(TerminalView::show_character_palette);
-
-    cx.add_action(TerminalView::test_search);
 }
 
 ///A terminal view, maintains the PTY's file handles and communicates with the terminal
@@ -162,14 +160,6 @@ impl TerminalView {
         }
     }
 
-    fn test_search(&mut self, _: &SearchTest, cx: &mut ViewContext<Self>) {
-        let search_string = "ttys";
-        self.terminal.update(cx, |term, _| {
-            term.search(search_string);
-        });
-        cx.notify();
-    }
-
     fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
         self.terminal.update(cx, |term, _| term.clear());
         cx.notify();
@@ -246,6 +236,19 @@ impl TerminalView {
         .detach();
     }
 
+    pub fn find_matches(
+        &mut self,
+        query: project::search::SearchQuery,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<Vec<RangeInclusive<Point>>> {
+        self.terminal
+            .update(cx, |term, cx| term.find_matches(query, cx))
+    }
+
+    pub fn terminal(&self) -> &ModelHandle<Terminal> {
+        &self.terminal
+    }
+
     fn next_blink_epoch(&mut self) -> usize {
         self.blink_epoch += 1;
         self.blink_epoch

crates/workspace/src/searchable.rs 🔗

@@ -10,8 +10,8 @@ use crate::{Item, ItemHandle, WeakItemHandle};
 
 #[derive(Debug)]
 pub enum SearchEvent {
-    ContentsUpdated,
-    SelectionsChanged,
+    MatchesInvalidated,
+    ActiveMatchChanged,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq)]
@@ -24,24 +24,27 @@ pub trait SearchableItem: Item {
     type Match: Any + Sync + Send + Clone;
 
     fn to_search_event(event: &Self::Event) -> Option<SearchEvent>;
-    fn clear_highlights(&mut self, cx: &mut ViewContext<Self>);
-    fn highlight_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>);
+    fn clear_matches(&mut self, cx: &mut ViewContext<Self>);
+    fn update_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>);
     fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String;
-    fn select_next_match_in_direction(
+    fn activate_next_match(
         &mut self,
         index: usize,
         direction: Direction,
         matches: Vec<Self::Match>,
         cx: &mut ViewContext<Self>,
     );
-    fn select_match_by_index(
+    fn activate_match_at_index(
         &mut self,
         index: usize,
         matches: Vec<Self::Match>,
         cx: &mut ViewContext<Self>,
     );
-    fn matches(&mut self, query: SearchQuery, cx: &mut ViewContext<Self>)
-        -> Task<Vec<Self::Match>>;
+    fn find_matches(
+        &mut self,
+        query: SearchQuery,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<Vec<Self::Match>>;
     fn active_match_index(
         &mut self,
         matches: Vec<Self::Match>,
@@ -107,11 +110,11 @@ impl<T: SearchableItem> SearchableItemHandle for ViewHandle<T> {
     }
 
     fn clear_highlights(&self, cx: &mut MutableAppContext) {
-        self.update(cx, |this, cx| this.clear_highlights(cx));
+        self.update(cx, |this, cx| this.clear_matches(cx));
     }
     fn highlight_matches(&self, matches: &Vec<Box<dyn Any + Send>>, cx: &mut MutableAppContext) {
         let matches = downcast_matches(matches);
-        self.update(cx, |this, cx| this.highlight_matches(matches, cx));
+        self.update(cx, |this, cx| this.update_matches(matches, cx));
     }
     fn query_suggestion(&self, cx: &mut MutableAppContext) -> String {
         self.update(cx, |this, cx| this.query_suggestion(cx))
@@ -125,7 +128,7 @@ impl<T: SearchableItem> SearchableItemHandle for ViewHandle<T> {
     ) {
         let matches = downcast_matches(matches);
         self.update(cx, |this, cx| {
-            this.select_next_match_in_direction(index, direction, matches, cx)
+            this.activate_next_match(index, direction, matches, cx)
         });
     }
     fn select_match_by_index(
@@ -136,7 +139,7 @@ impl<T: SearchableItem> SearchableItemHandle for ViewHandle<T> {
     ) {
         let matches = downcast_matches(matches);
         self.update(cx, |this, cx| {
-            this.select_match_by_index(index, matches, cx)
+            this.activate_match_at_index(index, matches, cx)
         });
     }
     fn matches(
@@ -144,7 +147,7 @@ impl<T: SearchableItem> SearchableItemHandle for ViewHandle<T> {
         query: SearchQuery,
         cx: &mut MutableAppContext,
     ) -> Task<Vec<Box<dyn Any + Send>>> {
-        let matches = self.update(cx, |this, cx| this.matches(query, cx));
+        let matches = self.update(cx, |this, cx| this.find_matches(query, cx));
         cx.foreground().spawn(async {
             let matches = matches.await;
             matches