add cycle mode to project search

Co-authored-by: Piotrek <piotr@zed.dev>
This commit is contained in:
KCaverly 2023-08-01 11:47:30 -04:00
parent 2e2d0a3884
commit c28ba3a11a

View File

@ -40,7 +40,13 @@ use workspace::{
actions!( actions!(
project_search, project_search,
[SearchInNew, ToggleFocus, NextField, ToggleSemanticSearch] [
SearchInNew,
ToggleFocus,
NextField,
ToggleSemanticSearch,
CycleMode
]
); );
#[derive(Default)] #[derive(Default)]
@ -54,6 +60,7 @@ pub fn init(cx: &mut AppContext) {
cx.add_action(ProjectSearchBar::search_in_new); cx.add_action(ProjectSearchBar::search_in_new);
cx.add_action(ProjectSearchBar::select_next_match); cx.add_action(ProjectSearchBar::select_next_match);
cx.add_action(ProjectSearchBar::select_prev_match); cx.add_action(ProjectSearchBar::select_prev_match);
cx.add_action(ProjectSearchBar::cycle_mode);
cx.capture_action(ProjectSearchBar::tab); cx.capture_action(ProjectSearchBar::tab);
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);
@ -103,6 +110,7 @@ pub struct ProjectSearchView {
included_files_editor: ViewHandle<Editor>, included_files_editor: ViewHandle<Editor>,
excluded_files_editor: ViewHandle<Editor>, excluded_files_editor: ViewHandle<Editor>,
filters_enabled: bool, filters_enabled: bool,
current_mode: SearchMode,
} }
struct SemanticSearchState { struct SemanticSearchState {
@ -111,6 +119,15 @@ struct SemanticSearchState {
_progress_task: Task<()>, _progress_task: Task<()>,
} }
// TODO: Update the default search mode to get from config
#[derive(Clone, Default, PartialEq)]
enum SearchMode {
#[default]
Text,
Semantic,
Regex,
}
pub struct ProjectSearchBar { pub struct ProjectSearchBar {
active_project_search: Option<ViewHandle<ProjectSearchView>>, active_project_search: Option<ViewHandle<ProjectSearchView>>,
subscription: Option<Subscription>, subscription: Option<Subscription>,
@ -596,6 +613,7 @@ impl ProjectSearchView {
included_files_editor, included_files_editor,
excluded_files_editor, excluded_files_editor,
filters_enabled, filters_enabled,
current_mode: Default::default(),
}; };
this.model_changed(cx); this.model_changed(cx);
this this
@ -910,7 +928,28 @@ impl ProjectSearchBar {
subscription: Default::default(), subscription: Default::default(),
} }
} }
fn cycle_mode(workspace: &mut Workspace, _: &CycleMode, cx: &mut ViewContext<Workspace>) {
if let Some(search_view) = workspace
.active_item(cx)
.and_then(|item| item.downcast::<ProjectSearchView>())
{
search_view.update(cx, |this, cx| {
let mode = &this.current_mode;
let next_text_state = if SemanticIndex::enabled(cx) {
SearchMode::Semantic
} else {
SearchMode::Regex
};
this.current_mode = match mode {
&SearchMode::Text => next_text_state,
&SearchMode::Semantic => SearchMode::Regex,
SearchMode::Regex => SearchMode::Text,
};
cx.notify();
})
}
}
fn search(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) { fn search(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
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.search(cx)); search_view.update(cx, |search_view, cx| search_view.search(cx));
@ -1184,14 +1223,15 @@ impl ProjectSearchBar {
.into_any() .into_any()
} }
fn render_option_button( fn render_regex_button(
&self, &self,
icon: &'static str, icon: &'static str,
option: SearchOptions, current_mode: SearchMode,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> AnyElement<Self> { ) -> AnyElement<Self> {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let is_active = self.is_option_enabled(option, cx); let is_active = current_mode == SearchMode::Regex;
let option = SearchOptions::REGEX;
MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| { MouseEventHandler::<Self, _>::new(option.bits as usize, cx, |state, cx| {
let theme = theme::current(cx); let theme = theme::current(cx);
let style = theme let style = theme
@ -1221,7 +1261,7 @@ impl ProjectSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let is_active = if let Some(search) = self.active_project_search.as_ref() { let is_active = if let Some(search) = self.active_project_search.as_ref() {
let search = search.read(cx); let search = search.read(cx);
search.semantic.is_some() search.current_mode == SearchMode::Semantic
} else { } else {
false false
}; };
@ -1256,7 +1296,7 @@ impl ProjectSearchBar {
let tooltip_style = theme::current(cx).tooltip.clone(); let tooltip_style = theme::current(cx).tooltip.clone();
let is_active = if let Some(search) = self.active_project_search.as_ref() { let is_active = if let Some(search) = self.active_project_search.as_ref() {
let search = search.read(cx); let search = search.read(cx);
search.semantic.is_none() && !self.is_option_enabled(SearchOptions::REGEX, cx) search.current_mode == SearchMode::Text
} else { } else {
false false
}; };
@ -1335,7 +1375,7 @@ impl View for ProjectSearchBar {
.aligned() .aligned()
.right() .right()
.flex(1.0, true); .flex(1.0, true);
let regex_button = self.render_option_button("Regex", SearchOptions::REGEX, cx); let regex_button = self.render_regex_button("Regex", search.current_mode.clone(), cx);
let row_spacing = theme.workspace.toolbar.container.padding.bottom; let row_spacing = theme.workspace.toolbar.container.padding.bottom;
let search = _search.read(cx); let search = _search.read(cx);
let filter_button = { let filter_button = {