@@ -4,9 +4,7 @@ mod query;
4
4
use crate :: {
5
5
alt,
6
6
compositor:: { self , Component , Compositor , Context , Event , EventResult } ,
7
- ctrl,
8
- job:: Callback ,
9
- key, shift,
7
+ ctrl, key, shift,
10
8
ui:: {
11
9
self ,
12
10
document:: { render_document, LineDecoration , LinePos , TextRenderer } ,
@@ -52,8 +50,6 @@ use helix_view::{
52
50
53
51
pub const ID : & str = "picker" ;
54
52
55
- use super :: overlay:: Overlay ;
56
-
57
53
pub const MIN_AREA_WIDTH_FOR_PREVIEW : u16 = 72 ;
58
54
/// Biggest file size to preview in bytes
59
55
pub const MAX_FILE_SIZE_FOR_PREVIEW : u64 = 10 * 1024 * 1024 ;
@@ -223,6 +219,11 @@ impl<T, D> Column<T, D> {
223
219
}
224
220
}
225
221
222
+ /// Returns a new list of options to replace the contents of the picker
223
+ /// when called with the current picker query,
224
+ type DynQueryCallback < T , D > =
225
+ fn ( String , & mut Editor , Arc < D > , & Injector < T , D > ) -> BoxFuture < ' static , anyhow:: Result < ( ) > > ;
226
+
226
227
pub struct Picker < T : ' static + Send + Sync , D : ' static > {
227
228
column_names : Vec < & ' static str > ,
228
229
columns : Arc < Vec < Column < T , D > > > ,
@@ -253,6 +254,8 @@ pub struct Picker<T: 'static + Send + Sync, D: 'static> {
253
254
file_fn : Option < FileCallback < T > > ,
254
255
/// An event handler for syntax highlighting the currently previewed file.
255
256
preview_highlight_handler : tokio:: sync:: mpsc:: Sender < Arc < Path > > ,
257
+ dynamic_query_running : bool ,
258
+ dynamic_query_handler : Option < tokio:: sync:: mpsc:: Sender < String > > ,
256
259
}
257
260
258
261
impl < T : ' static + Send + Sync , D : ' static + Send + Sync > Picker < T , D > {
@@ -362,6 +365,8 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
362
365
read_buffer : Vec :: with_capacity ( 1024 ) ,
363
366
file_fn : None ,
364
367
preview_highlight_handler : handlers:: PreviewHighlightHandler :: < T , D > :: default ( ) . spawn ( ) ,
368
+ dynamic_query_running : false ,
369
+ dynamic_query_handler : None ,
365
370
}
366
371
}
367
372
@@ -396,12 +401,11 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
396
401
self
397
402
}
398
403
399
- pub fn set_options ( & mut self , new_options : Vec < T > ) {
400
- self . matcher . restart ( false ) ;
401
- let injector = self . matcher . injector ( ) ;
402
- for item in new_options {
403
- inject_nucleo_item ( & injector, & self . columns , item, & self . editor_data ) ;
404
- }
404
+ pub fn with_dynamic_query ( mut self , callback : DynQueryCallback < T , D > ) -> Self {
405
+ let handler = handlers:: DynamicQueryHandler :: new ( callback) . spawn ( ) ;
406
+ helix_event:: send_blocking ( & handler, self . primary_query ( ) . to_string ( ) ) ;
407
+ self . dynamic_query_handler = Some ( handler) ;
408
+ self
405
409
}
406
410
407
411
/// Move the cursor by a number of lines, either down (`Forward`) or up (`Backward`)
@@ -504,6 +508,9 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
504
508
. reparse ( i, pattern, CaseMatching :: Smart , append) ;
505
509
}
506
510
self . query = new_query;
511
+ if let Some ( handler) = & self . dynamic_query_handler {
512
+ helix_event:: send_blocking ( handler, self . primary_query ( ) . to_string ( ) ) ;
513
+ }
507
514
}
508
515
}
509
516
EventResult :: Consumed ( None )
@@ -615,7 +622,11 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
615
622
616
623
let count = format ! (
617
624
"{}{}/{}" ,
618
- if status. running { "(running) " } else { "" } ,
625
+ if status. running || self . dynamic_query_running {
626
+ "(running) "
627
+ } else {
628
+ ""
629
+ } ,
619
630
snapshot. matched_item_count( ) ,
620
631
snapshot. item_count( ) ,
621
632
) ;
@@ -1027,74 +1038,3 @@ impl<T: 'static + Send + Sync, D> Drop for Picker<T, D> {
1027
1038
}
1028
1039
1029
1040
type PickerCallback < T > = Box < dyn Fn ( & mut Context , & T , Action ) > ;
1030
-
1031
- /// Returns a new list of options to replace the contents of the picker
1032
- /// when called with the current picker query,
1033
- pub type DynQueryCallback < T > =
1034
- Box < dyn Fn ( String , & mut Editor ) -> BoxFuture < ' static , anyhow:: Result < Vec < T > > > > ;
1035
-
1036
- /// A picker that updates its contents via a callback whenever the
1037
- /// query string changes. Useful for live grep, workspace symbols, etc.
1038
- pub struct DynamicPicker < T : ' static + Send + Sync , D : ' static + Send + Sync > {
1039
- file_picker : Picker < T , D > ,
1040
- query_callback : DynQueryCallback < T > ,
1041
- query : String ,
1042
- }
1043
-
1044
- impl < T : Send + Sync , D : Send + Sync > DynamicPicker < T , D > {
1045
- pub fn new ( file_picker : Picker < T , D > , query_callback : DynQueryCallback < T > ) -> Self {
1046
- Self {
1047
- file_picker,
1048
- query_callback,
1049
- query : String :: new ( ) ,
1050
- }
1051
- }
1052
- }
1053
-
1054
- impl < T : Send + Sync + ' static , D : Send + Sync + ' static > Component for DynamicPicker < T , D > {
1055
- fn render ( & mut self , area : Rect , surface : & mut Surface , cx : & mut Context ) {
1056
- self . file_picker . render ( area, surface, cx) ;
1057
- }
1058
-
1059
- fn handle_event ( & mut self , event : & Event , cx : & mut Context ) -> EventResult {
1060
- let event_result = self . file_picker . handle_event ( event, cx) ;
1061
- let Some ( current_query) = self . file_picker . primary_query ( ) else {
1062
- return event_result;
1063
- } ;
1064
-
1065
- if !matches ! ( event, Event :: IdleTimeout ) || self . query == * current_query {
1066
- return event_result;
1067
- }
1068
-
1069
- self . query = current_query. to_string ( ) ;
1070
-
1071
- let new_options = ( self . query_callback ) ( current_query. to_owned ( ) , cx. editor ) ;
1072
-
1073
- cx. jobs . callback ( async move {
1074
- let new_options = new_options. await ?;
1075
- let callback = Callback :: EditorCompositor ( Box :: new ( move |_editor, compositor| {
1076
- // Wrapping of pickers in overlay is done outside the picker code,
1077
- // so this is fragile and will break if wrapped in some other widget.
1078
- let picker = match compositor. find_id :: < Overlay < Self > > ( ID ) {
1079
- Some ( overlay) => & mut overlay. content . file_picker ,
1080
- None => return ,
1081
- } ;
1082
- picker. set_options ( new_options) ;
1083
- } ) ) ;
1084
- anyhow:: Ok ( callback)
1085
- } ) ;
1086
- EventResult :: Consumed ( None )
1087
- }
1088
-
1089
- fn cursor ( & self , area : Rect , ctx : & Editor ) -> ( Option < Position > , CursorKind ) {
1090
- self . file_picker . cursor ( area, ctx)
1091
- }
1092
-
1093
- fn required_size ( & mut self , viewport : ( u16 , u16 ) ) -> Option < ( u16 , u16 ) > {
1094
- self . file_picker . required_size ( viewport)
1095
- }
1096
-
1097
- fn id ( & self ) -> Option < & ' static str > {
1098
- Some ( ID )
1099
- }
1100
- }
0 commit comments