Terminal implements important half of search protocol

This commit is contained in:
Mikayla Maki 2022-08-31 17:41:53 -07:00
parent 63d9d29762
commit 3f11fd3b8b
8 changed files with 249 additions and 119 deletions

View file

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

View file

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

View file

@ -174,7 +174,9 @@ impl ToolbarItemView for BufferSearchBar {
cx, cx,
Box::new(move |search_event, cx| { Box::new(move |search_event, cx| {
if let Some(this) = handle.upgrade(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 { match event {
SearchEvent::ContentsUpdated => self.update_matches(false, cx), SearchEvent::MatchesInvalidated => self.update_matches(false, cx),
SearchEvent::SelectionsChanged => self.update_match_index(cx), SearchEvent::ActiveMatchChanged => self.update_match_index(cx),
} }
} }

View file

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

View file

@ -1,17 +1,20 @@
use crate::terminal_view::TerminalView; use crate::terminal_view::TerminalView;
use crate::{Event, Terminal, TerminalBuilder, TerminalError}; use crate::{Event, Terminal, TerminalBuilder, TerminalError};
use alacritty_terminal::index::Point;
use dirs::home_dir; use dirs::home_dir;
use gpui::{ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, View, actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, Task,
ViewContext, ViewHandle, View, ViewContext, ViewHandle,
}; };
use workspace::searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle};
use workspace::{Item, Workspace}; use workspace::{Item, Workspace};
use crate::TerminalSize; use crate::TerminalSize;
use project::{LocalWorktree, Project, ProjectPath}; use project::{LocalWorktree, Project, ProjectPath};
use settings::{AlternateScroll, Settings, WorkingDirectory}; use settings::{AlternateScroll, Settings, WorkingDirectory};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::ops::RangeInclusive;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::terminal_element::TerminalElement; use crate::terminal_element::TerminalElement;
@ -328,6 +331,98 @@ impl Item for TerminalContainer {
fn should_close_item_on_event(event: &Self::Event) -> bool { fn should_close_item_on_event(event: &Self::Event) -> bool {
matches!(event, &Event::CloseTerminal) 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. ///Get's the working directory for the given workspace, respecting the user's settings.

View file

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

View file

@ -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 context_menu::{ContextMenu, ContextMenuItem};
use gpui::{ use gpui::{
actions, actions,
@ -8,8 +8,8 @@ use gpui::{
geometry::vector::Vector2F, geometry::vector::Vector2F,
impl_internal_actions, impl_internal_actions,
keymap::Keystroke, keymap::Keystroke,
AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, Task,
ViewContext, ViewHandle, View, ViewContext, ViewHandle,
}; };
use settings::{Settings, TerminalBlink}; use settings::{Settings, TerminalBlink};
use smol::Timer; use smol::Timer;
@ -58,8 +58,6 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(TerminalView::paste); cx.add_action(TerminalView::paste);
cx.add_action(TerminalView::clear); cx.add_action(TerminalView::clear);
cx.add_action(TerminalView::show_character_palette); 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 ///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>) { fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
self.terminal.update(cx, |term, _| term.clear()); self.terminal.update(cx, |term, _| term.clear());
cx.notify(); cx.notify();
@ -246,6 +236,19 @@ impl TerminalView {
.detach(); .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 { fn next_blink_epoch(&mut self) -> usize {
self.blink_epoch += 1; self.blink_epoch += 1;
self.blink_epoch self.blink_epoch

View file

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