diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 7a4f1ad1a74cdc78486a1ff93b4c749de22afaeb..44586b610231864e5e5a9e16128f627d6de96880 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -120,7 +120,7 @@ struct SemanticSearchState { } // TODO: Update the default search mode to get from config -#[derive(Clone, Default, PartialEq)] +#[derive(Copy, Clone, Default, PartialEq)] enum SearchMode { #[default] Text, @@ -282,29 +282,67 @@ impl View for ProjectSearchView { enum Status {} let theme = theme::current(cx).clone(); - let text = if model.pending_search.is_some() { + + // If Search is Active -> Major: Searching..., Minor: None + // If Semantic -> Major: "Search using Natural Language", Minor: {Status}/n{ex...}/n{ex...} + // If Regex -> Major: "Search using Regex", Minor: {ex...} + // If Text -> Major: "Text search all files and folders", Minor: {...} + + let current_mode = self.current_mode; + let major_text = if model.pending_search.is_some() { Cow::Borrowed("Searching...") - } else if let Some(semantic) = &self.semantic { + } else { + match current_mode { + SearchMode::Text => Cow::Borrowed("Text search all files and folders"), + SearchMode::Semantic => { + Cow::Borrowed("Search all files and folders using Natural Language") + } + SearchMode::Regex => Cow::Borrowed("Regex search all files and folders"), + } + }; + + let semantic_status = if let Some(semantic) = &self.semantic { if semantic.outstanding_file_count > 0 { - Cow::Owned(format!( - "Indexing. {} of {}...", + let dots_count = semantic.outstanding_file_count % 3 + 1; + let dots: String = std::iter::repeat('.').take(dots_count).collect(); + format!( + "Indexing. {} of {}{dots}", semantic.file_count - semantic.outstanding_file_count, semantic.file_count - )) + ) } else { - Cow::Borrowed("Indexing complete") + "Indexing complete".to_string() } - } else if self.query_editor.read(cx).text(cx).is_empty() { - Cow::Borrowed("Text search all files and folders") } else { - Cow::Borrowed("No results") + "This is an invalid state".to_string() + }; + + let minor_text = match current_mode { + SearchMode::Semantic => [ + semantic_status, + "ex. list all available languages".to_owned(), + ], + _ => [ + "Include/exclude specific paths with the filter option.".to_owned(), + "Matching exact word and/or casing is available too.".to_owned(), + ], }; MouseEventHandler::::new(0, cx, |_, _| { Flex::column() .with_child(Flex::column().contained().flex(1., true)) .with_child( - Label::new(text, theme.search.results_status.clone()) + Flex::column() + .align_children_center() + .with_child(Label::new( + major_text, + theme.search.major_results_status.clone(), + )) + .with_children( + minor_text.into_iter().map(|x| { + Label::new(x, theme.search.minor_results_status.clone()) + }), + ) .aligned() .top() .contained() @@ -1060,6 +1098,9 @@ impl ProjectSearchBar { if let Some(search_view) = self.active_project_search.as_ref() { search_view.update(cx, |search_view, cx| { search_view.search_options.toggle(option); + if option.contains(SearchOptions::REGEX) { + search_view.current_mode = SearchMode::Regex; + } search_view.semantic = None; search_view.search(cx); }); @@ -1096,6 +1137,7 @@ impl ProjectSearchBar { 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(); @@ -1315,7 +1357,13 @@ impl ProjectSearchBar { .with_style(style.container) }) .on_click(MouseButton::Left, move |_, this, cx| { - this.toggle_semantic_search(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::( @@ -1425,7 +1473,6 @@ impl View for ProjectSearchBar { let search = _search.read(cx); let icon_style = theme.search.editor_icon.clone(); - // " let query = Flex::row() .with_child( Svg::for_style(icon_style.icon) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index db6785c6fd83a6663b5650cc4fe5bc0cb3ab45f0..b3e65d9fda628173f631660e0f9922994630c8fd 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -383,7 +383,8 @@ pub struct Search { pub action_button: Interactive, pub match_background: Color, pub match_index: ContainedText, - pub results_status: TextStyle, + pub major_results_status: TextStyle, + pub minor_results_status: TextStyle, pub dismiss_button: Interactive, pub editor_icon: IconStyle, } diff --git a/styles/src/style_tree/search.ts b/styles/src/style_tree/search.ts index c2357f53b63618d60a8efcd35220886d6d17a0a8..9f72cfc42468660b63b7284c3d9e3dbfb2536b54 100644 --- a/styles/src/style_tree/search.ts +++ b/styles/src/style_tree/search.ts @@ -140,9 +140,13 @@ export default function search(): any { right: 6, }, }, - results_status: { + major_results_status: { ...text(theme.highest, "mono", "on"), - size: 18, + size: 15, + }, + minor_results_status: { + ...text(theme.highest, "mono", "variant"), + size: 13, }, dismiss_button: interactive({ base: {