@@ -57,7 +57,9 @@ actions!(
5757 /// Moves to the next input field.
5858 NextField ,
5959 /// Toggles the search filters panel.
60- ToggleFilters
60+ ToggleFilters ,
61+ /// Toggles collapse/expand state of all search result excerpts.
62+ ToggleAllSearchResults
6163 ]
6264) ;
6365
@@ -120,6 +122,20 @@ pub fn init(cx: &mut App) {
120122 ProjectSearchView :: search_in_new ( workspace, action, window, cx)
121123 } ) ;
122124
125+ register_workspace_action_for_present_search (
126+ workspace,
127+ |workspace, action : & ToggleAllSearchResults , window, cx| {
128+ if let Some ( search_view) = workspace
129+ . active_item ( cx)
130+ . and_then ( |item| item. downcast :: < ProjectSearchView > ( ) )
131+ {
132+ search_view. update ( cx, |search_view, cx| {
133+ search_view. toggle_all_search_results ( action, window, cx) ;
134+ } ) ;
135+ }
136+ } ,
137+ ) ;
138+
123139 register_workspace_action_for_present_search (
124140 workspace,
125141 |workspace, _: & menu:: Cancel , window, cx| {
@@ -219,6 +235,7 @@ pub struct ProjectSearchView {
219235 replace_enabled : bool ,
220236 included_opened_only : bool ,
221237 regex_language : Option < Arc < Language > > ,
238+ results_collapsed : bool ,
222239 _subscriptions : Vec < Subscription > ,
223240}
224241
@@ -651,6 +668,44 @@ impl Item for ProjectSearchView {
651668 fn breadcrumbs ( & self , theme : & theme:: Theme , cx : & App ) -> Option < Vec < BreadcrumbText > > {
652669 self . results_editor . breadcrumbs ( theme, cx)
653670 }
671+
672+ fn breadcrumb_prefix (
673+ & self ,
674+ _window : & mut Window ,
675+ cx : & mut Context < Self > ,
676+ ) -> Option < gpui:: AnyElement > {
677+ if !self . has_matches ( ) {
678+ return None ;
679+ }
680+
681+ let is_collapsed = self . results_collapsed ;
682+
683+ let ( icon, tooltip_label) = if is_collapsed {
684+ ( IconName :: ChevronUpDown , "Expand All Search Results" )
685+ } else {
686+ ( IconName :: ChevronDownUp , "Collapse All Search Results" )
687+ } ;
688+
689+ let focus_handle = self . query_editor . focus_handle ( cx) ;
690+
691+ Some (
692+ IconButton :: new ( "project-search-collapse-expand" , icon)
693+ . shape ( IconButtonShape :: Square )
694+ . icon_size ( IconSize :: Small )
695+ . tooltip ( move |_, cx| {
696+ Tooltip :: for_action_in (
697+ tooltip_label,
698+ & ToggleAllSearchResults ,
699+ & focus_handle,
700+ cx,
701+ )
702+ } )
703+ . on_click ( cx. listener ( |this, _, window, cx| {
704+ this. toggle_all_search_results ( & ToggleAllSearchResults , window, cx) ;
705+ } ) )
706+ . into_any_element ( ) ,
707+ )
708+ }
654709}
655710
656711impl ProjectSearchView {
@@ -753,6 +808,34 @@ impl ProjectSearchView {
753808 } ) ;
754809 }
755810
811+ fn toggle_all_search_results (
812+ & mut self ,
813+ _: & ToggleAllSearchResults ,
814+ _window : & mut Window ,
815+ cx : & mut Context < Self > ,
816+ ) {
817+ self . results_collapsed = !self . results_collapsed ;
818+ self . update_results_visibility ( cx) ;
819+ }
820+
821+ fn update_results_visibility ( & mut self , cx : & mut Context < Self > ) {
822+ self . results_editor . update ( cx, |editor, cx| {
823+ let multibuffer = editor. buffer ( ) . read ( cx) ;
824+ let buffer_ids = multibuffer. excerpt_buffer_ids ( ) ;
825+
826+ if self . results_collapsed {
827+ for buffer_id in buffer_ids {
828+ editor. fold_buffer ( buffer_id, cx) ;
829+ }
830+ } else {
831+ for buffer_id in buffer_ids {
832+ editor. unfold_buffer ( buffer_id, cx) ;
833+ }
834+ }
835+ } ) ;
836+ cx. notify ( ) ;
837+ }
838+
756839 pub fn new (
757840 workspace : WeakEntity < Workspace > ,
758841 entity : Entity < ProjectSearch > ,
@@ -911,8 +994,10 @@ impl ProjectSearchView {
911994 replace_enabled : false ,
912995 included_opened_only : false ,
913996 regex_language : None ,
997+ results_collapsed : false ,
914998 _subscriptions : subscriptions,
915999 } ;
1000+
9161001 this. entity_changed ( window, cx) ;
9171002 this
9181003 }
@@ -1411,6 +1496,7 @@ impl ProjectSearchView {
14111496
14121497 fn entity_changed ( & mut self , window : & mut Window , cx : & mut Context < Self > ) {
14131498 let match_ranges = self . entity . read ( cx) . match_ranges . clone ( ) ;
1499+
14141500 if match_ranges. is_empty ( ) {
14151501 self . active_match_index = None ;
14161502 self . results_editor . update ( cx, |editor, cx| {
@@ -1968,6 +2054,8 @@ impl Render for ProjectSearchBar {
19682054 } )
19692055 . unwrap_or_else ( || "0/0" . to_string ( ) ) ;
19702056
2057+ let query_focus = search. query_editor . focus_handle ( cx) ;
2058+
19712059 let query_column = input_base_styles ( InputPanel :: Query )
19722060 . on_action ( cx. listener ( |this, action, window, cx| this. confirm ( action, window, cx) ) )
19732061 . on_action ( cx. listener ( |this, action, window, cx| {
@@ -1997,11 +2085,9 @@ impl Render for ProjectSearchBar {
19972085 ) ) ,
19982086 ) ;
19992087
2000- let query_focus = search. query_editor . focus_handle ( cx) ;
2001-
20022088 let matches_column = h_flex ( )
2003- . pl_2 ( )
2004- . ml_2 ( )
2089+ . ml_1 ( )
2090+ . pl_1p5 ( )
20052091 . border_l_1 ( )
20062092 . border_color ( theme_colors. border_variant )
20072093 . child ( render_action_button (
0 commit comments