mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-15 23:03:57 +00:00
add kill_search function to stop searching on mode change
This commit is contained in:
parent
7b43b0d4f1
commit
acf78f5fb4
1 changed files with 13 additions and 224 deletions
|
@ -1,6 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleRegex,
|
SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
|
||||||
ToggleWholeWord,
|
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
@ -22,7 +21,7 @@ use gpui::{
|
||||||
Action, AnyElement, AnyViewHandle, AppContext, Entity, ModelContext, ModelHandle, Subscription,
|
Action, AnyElement, AnyViewHandle, AppContext, Entity, ModelContext, ModelHandle, Subscription,
|
||||||
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use gpui::{scene::Path, Border, LayoutContext};
|
use gpui::{scene::Path, LayoutContext};
|
||||||
use menu::Confirm;
|
use menu::Confirm;
|
||||||
use postage::stream::Stream;
|
use postage::stream::Stream;
|
||||||
use project::{search::SearchQuery, Entry, Project};
|
use project::{search::SearchQuery, Entry, Project};
|
||||||
|
@ -50,7 +49,6 @@ actions!(
|
||||||
SearchInNew,
|
SearchInNew,
|
||||||
ToggleFocus,
|
ToggleFocus,
|
||||||
NextField,
|
NextField,
|
||||||
ToggleSemanticSearch,
|
|
||||||
CycleMode,
|
CycleMode,
|
||||||
ActivateTextMode,
|
ActivateTextMode,
|
||||||
ActivateSemanticMode,
|
ActivateSemanticMode,
|
||||||
|
@ -74,7 +72,6 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.capture_action(ProjectSearchBar::tab_previous);
|
cx.capture_action(ProjectSearchBar::tab_previous);
|
||||||
add_toggle_option_action::<ToggleCaseSensitive>(SearchOptions::CASE_SENSITIVE, cx);
|
add_toggle_option_action::<ToggleCaseSensitive>(SearchOptions::CASE_SENSITIVE, cx);
|
||||||
add_toggle_option_action::<ToggleWholeWord>(SearchOptions::WHOLE_WORD, cx);
|
add_toggle_option_action::<ToggleWholeWord>(SearchOptions::WHOLE_WORD, cx);
|
||||||
add_toggle_option_action::<ToggleRegex>(SearchOptions::REGEX, cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_toggle_option_action<A: Action>(option: SearchOptions, cx: &mut AppContext) {
|
fn add_toggle_option_action<A: Action>(option: SearchOptions, cx: &mut AppContext) {
|
||||||
|
@ -234,6 +231,12 @@ impl ProjectSearch {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn kill_search(&mut self) {
|
||||||
|
self.active_query = None;
|
||||||
|
self.match_ranges.clear();
|
||||||
|
self.pending_search = None;
|
||||||
|
}
|
||||||
|
|
||||||
fn search(&mut self, query: SearchQuery, cx: &mut ModelContext<Self>) {
|
fn search(&mut self, query: SearchQuery, cx: &mut ModelContext<Self>) {
|
||||||
let search = self
|
let search = self
|
||||||
.project
|
.project
|
||||||
|
@ -626,6 +629,7 @@ impl Item for ProjectSearchView {
|
||||||
|
|
||||||
impl ProjectSearchView {
|
impl ProjectSearchView {
|
||||||
fn activate_search_mode(&mut self, mode: SearchMode, cx: &mut ViewContext<Self>) {
|
fn activate_search_mode(&mut self, mode: SearchMode, cx: &mut ViewContext<Self>) {
|
||||||
|
self.model.update(cx, |model, _| model.kill_search());
|
||||||
self.current_mode = mode;
|
self.current_mode = mode;
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
|
@ -674,13 +678,13 @@ impl ProjectSearchView {
|
||||||
}
|
}
|
||||||
SearchMode::Regex => {
|
SearchMode::Regex => {
|
||||||
if !self.is_option_enabled(SearchOptions::REGEX) {
|
if !self.is_option_enabled(SearchOptions::REGEX) {
|
||||||
self.toggle_search_option(SearchOptions::REGEX, cx);
|
self.toggle_search_option(SearchOptions::REGEX);
|
||||||
}
|
}
|
||||||
self.semantic = None;
|
self.semantic = None;
|
||||||
}
|
}
|
||||||
SearchMode::Text => {
|
SearchMode::Text => {
|
||||||
if self.is_option_enabled(SearchOptions::REGEX) {
|
if self.is_option_enabled(SearchOptions::REGEX) {
|
||||||
self.toggle_search_option(SearchOptions::REGEX, cx);
|
self.toggle_search_option(SearchOptions::REGEX);
|
||||||
}
|
}
|
||||||
self.semantic = None;
|
self.semantic = None;
|
||||||
}
|
}
|
||||||
|
@ -923,7 +927,7 @@ impl ProjectSearchView {
|
||||||
|
|
||||||
Some((included_files, excluded_files))
|
Some((included_files, excluded_files))
|
||||||
}
|
}
|
||||||
fn toggle_search_option(&mut self, option: SearchOptions, cx: &mut ViewContext<Self>) {
|
fn toggle_search_option(&mut self, option: SearchOptions) {
|
||||||
self.search_options.toggle(option);
|
self.search_options.toggle(option);
|
||||||
self.semantic = None;
|
self.semantic = None;
|
||||||
}
|
}
|
||||||
|
@ -1373,7 +1377,7 @@ impl ProjectSearchBar {
|
||||||
fn toggle_search_option(&mut self, option: SearchOptions, cx: &mut ViewContext<Self>) -> bool {
|
fn toggle_search_option(&mut self, option: SearchOptions, cx: &mut ViewContext<Self>) -> bool {
|
||||||
if let Some(search_view) = self.active_project_search.as_ref() {
|
if let Some(search_view) = self.active_project_search.as_ref() {
|
||||||
search_view.update(cx, |search_view, cx| {
|
search_view.update(cx, |search_view, cx| {
|
||||||
search_view.toggle_search_option(option, cx);
|
search_view.toggle_search_option(option);
|
||||||
});
|
});
|
||||||
cx.notify();
|
cx.notify();
|
||||||
true
|
true
|
||||||
|
@ -1403,62 +1407,6 @@ impl ProjectSearchBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_semantic_search(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
|
||||||
if let Some(search_view) = self.active_project_search.as_ref() {
|
|
||||||
search_view.update(cx, |search_view, cx| {
|
|
||||||
if search_view.semantic.is_some() {
|
|
||||||
search_view.semantic = None;
|
|
||||||
} else if let Some(semantic_index) = SemanticIndex::global(cx) {
|
|
||||||
search_view.current_mode = SearchMode::Semantic;
|
|
||||||
// TODO: confirm that it's ok to send this project
|
|
||||||
search_view.search_options = SearchOptions::none();
|
|
||||||
|
|
||||||
let project = search_view.model.read(cx).project.clone();
|
|
||||||
let index_task = semantic_index.update(cx, |semantic_index, cx| {
|
|
||||||
semantic_index.index_project(project, cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
cx.spawn(|search_view, mut cx| async move {
|
|
||||||
let (files_to_index, mut files_remaining_rx) = index_task.await?;
|
|
||||||
|
|
||||||
search_view.update(&mut cx, |search_view, cx| {
|
|
||||||
cx.notify();
|
|
||||||
search_view.semantic = Some(SemanticSearchState {
|
|
||||||
file_count: files_to_index,
|
|
||||||
outstanding_file_count: files_to_index,
|
|
||||||
_progress_task: cx.spawn(|search_view, mut cx| async move {
|
|
||||||
while let Some(count) = files_remaining_rx.recv().await {
|
|
||||||
search_view
|
|
||||||
.update(&mut cx, |search_view, cx| {
|
|
||||||
if let Some(semantic_search_state) =
|
|
||||||
&mut search_view.semantic
|
|
||||||
{
|
|
||||||
semantic_search_state.outstanding_file_count =
|
|
||||||
count;
|
|
||||||
cx.notify();
|
|
||||||
if count == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
})?;
|
|
||||||
anyhow::Ok(())
|
|
||||||
})
|
|
||||||
.detach_and_log_err(cx);
|
|
||||||
}
|
|
||||||
cx.notify();
|
|
||||||
});
|
|
||||||
cx.notify();
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_nav_button(
|
fn render_nav_button(
|
||||||
&self,
|
&self,
|
||||||
icon: &'static str,
|
icon: &'static str,
|
||||||
|
@ -1629,165 +1577,6 @@ impl ProjectSearchBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_regex_button(
|
|
||||||
&self,
|
|
||||||
icon: &'static str,
|
|
||||||
current_mode: SearchMode,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> AnyElement<Self> {
|
|
||||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
|
||||||
let is_active = current_mode == SearchMode::Regex; //self.is_option_enabled(option, cx);
|
|
||||||
let option = SearchOptions::REGEX;
|
|
||||||
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| {
|
|
||||||
let theme = theme::current(cx);
|
|
||||||
let mut style = theme
|
|
||||||
.search
|
|
||||||
.mode_button
|
|
||||||
.in_state(is_active)
|
|
||||||
.style_for(state)
|
|
||||||
.clone();
|
|
||||||
style.container.border.right = false;
|
|
||||||
style.container.padding.right -= theme.search.mode_filling_width;
|
|
||||||
style.container.corner_radius = 0.;
|
|
||||||
debug_assert!(style.container.padding.right >= 0.);
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Label::new(icon, style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
ButtonSide::right(
|
|
||||||
style
|
|
||||||
.container
|
|
||||||
.background_color
|
|
||||||
.unwrap_or_else(gpui::color::Color::transparent_black),
|
|
||||||
)
|
|
||||||
.with_border(style.container.border.width, style.container.border.color)
|
|
||||||
.contained()
|
|
||||||
.constrained()
|
|
||||||
.with_max_width(theme.search.mode_filling_width)
|
|
||||||
.aligned()
|
|
||||||
.bottom(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
|
||||||
this.toggle_search_option(option, cx);
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.with_tooltip::<Self>(
|
|
||||||
option.bits as usize,
|
|
||||||
format!("Toggle {}", option.label()),
|
|
||||||
Some(option.to_toggle_action()),
|
|
||||||
tooltip_style,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_semantic_search_button(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
|
||||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
|
||||||
let is_active = if let Some(search) = self.active_project_search.as_ref() {
|
|
||||||
let search = search.read(cx);
|
|
||||||
search.current_mode == SearchMode::Semantic
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let region_id = 3;
|
|
||||||
|
|
||||||
MouseEventHandler::<Self, _>::new(region_id, cx, |state, cx| {
|
|
||||||
let theme = theme::current(cx);
|
|
||||||
let mut style = theme
|
|
||||||
.search
|
|
||||||
.mode_button
|
|
||||||
.in_state(is_active)
|
|
||||||
.style_for(state)
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
style.container.corner_radius = 0.;
|
|
||||||
|
|
||||||
Label::new("Semantic", style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
})
|
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
|
||||||
this.toggle_semantic_search(cx);
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.with_tooltip::<Self>(
|
|
||||||
region_id,
|
|
||||||
format!("Toggle Semantic Search"),
|
|
||||||
Some(Box::new(ToggleSemanticSearch)),
|
|
||||||
tooltip_style,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
fn render_text_search_button(&self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
|
||||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
|
||||||
let is_active = if let Some(search) = self.active_project_search.as_ref() {
|
|
||||||
let search = search.read(cx);
|
|
||||||
search.current_mode == SearchMode::Text
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let region_id = 4;
|
|
||||||
enum NormalSearchTag {}
|
|
||||||
MouseEventHandler::<NormalSearchTag, _>::new(region_id, cx, |state, cx| {
|
|
||||||
let theme = theme::current(cx);
|
|
||||||
let mut style = theme
|
|
||||||
.search
|
|
||||||
.mode_button
|
|
||||||
.in_state(is_active)
|
|
||||||
.style_for(state)
|
|
||||||
.clone();
|
|
||||||
style.container.border.left = false;
|
|
||||||
style.container.padding.left -= theme.search.mode_filling_width;
|
|
||||||
debug_assert!(style.container.padding.left >= 0.);
|
|
||||||
style.container.corner_radius = 0.;
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
ButtonSide::left(
|
|
||||||
style
|
|
||||||
.container
|
|
||||||
.background_color
|
|
||||||
.unwrap_or_else(gpui::color::Color::transparent_black),
|
|
||||||
)
|
|
||||||
.with_border(style.container.border.width, style.container.border.color)
|
|
||||||
.contained()
|
|
||||||
.constrained()
|
|
||||||
.with_max_width(theme.search.mode_filling_width)
|
|
||||||
.aligned()
|
|
||||||
.bottom(),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
Label::new("Text", style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
|
||||||
if let Some(search) = this.active_project_search.as_mut() {
|
|
||||||
search.update(cx, |this, cx| {
|
|
||||||
this.semantic = None;
|
|
||||||
this.current_mode = SearchMode::Text;
|
|
||||||
cx.notify();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.with_tooltip::<NormalSearchTag>(
|
|
||||||
region_id,
|
|
||||||
format!("Toggle Normal Search"),
|
|
||||||
None,
|
|
||||||
tooltip_style,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_option_enabled(&self, option: SearchOptions, cx: &AppContext) -> bool {
|
fn is_option_enabled(&self, option: SearchOptions, cx: &AppContext) -> bool {
|
||||||
if let Some(search) = self.active_project_search.as_ref() {
|
if let Some(search) = self.active_project_search.as_ref() {
|
||||||
search.read(cx).search_options.contains(option)
|
search.read(cx).search_options.contains(option)
|
||||||
|
|
Loading…
Reference in a new issue