@@ -17,6 +17,7 @@ mod text_decorations;
1717use crate :: compositor:: Compositor ;
1818use crate :: filter_picker_entry;
1919use crate :: job:: { self , Callback } ;
20+ use crate :: ui:: completers:: CompletionResult ;
2021pub use completion:: { Completion , CompletionItem } ;
2122pub use editor:: EditorView ;
2223use helix_stdx:: rope;
@@ -36,7 +37,7 @@ pub fn prompt(
3637 cx : & mut crate :: commands:: Context ,
3738 prompt : std:: borrow:: Cow < ' static , str > ,
3839 history_register : Option < char > ,
39- completion_fn : impl FnMut ( & Editor , & str ) -> Vec < prompt :: Completion > + ' static ,
40+ completion_fn : impl FnMut ( & Editor , & str ) -> CompletionResult + ' static ,
4041 callback_fn : impl FnMut ( & mut crate :: compositor:: Context , & str , PromptEvent ) + ' static ,
4142) {
4243 let mut prompt = Prompt :: new ( prompt, history_register, completion_fn, callback_fn) ;
@@ -45,24 +46,11 @@ pub fn prompt(
4546 cx. push_layer ( Box :: new ( prompt) ) ;
4647}
4748
48- pub fn prompt_with_input (
49- cx : & mut crate :: commands:: Context ,
50- prompt : std:: borrow:: Cow < ' static , str > ,
51- input : String ,
52- history_register : Option < char > ,
53- completion_fn : impl FnMut ( & Editor , & str ) -> Vec < prompt:: Completion > + ' static ,
54- callback_fn : impl FnMut ( & mut crate :: compositor:: Context , & str , PromptEvent ) + ' static ,
55- ) {
56- let prompt = Prompt :: new ( prompt, history_register, completion_fn, callback_fn)
57- . with_line ( input, cx. editor ) ;
58- cx. push_layer ( Box :: new ( prompt) ) ;
59- }
60-
6149pub fn regex_prompt (
6250 cx : & mut crate :: commands:: Context ,
6351 prompt : std:: borrow:: Cow < ' static , str > ,
6452 history_register : Option < char > ,
65- completion_fn : impl FnMut ( & Editor , & str ) -> Vec < prompt :: Completion > + ' static ,
53+ completion_fn : impl FnMut ( & Editor , & str ) -> CompletionResult + ' static ,
6654 fun : impl Fn ( & mut crate :: compositor:: Context , rope:: Regex , PromptEvent ) + ' static ,
6755) {
6856 raw_regex_prompt (
@@ -77,7 +65,7 @@ pub fn raw_regex_prompt(
7765 cx : & mut crate :: commands:: Context ,
7866 prompt : std:: borrow:: Cow < ' static , str > ,
7967 history_register : Option < char > ,
80- completion_fn : impl FnMut ( & Editor , & str ) -> Vec < prompt :: Completion > + ' static ,
68+ completion_fn : impl FnMut ( & Editor , & str ) -> CompletionResult + ' static ,
8169 fun : impl Fn ( & mut crate :: compositor:: Context , rope:: Regex , & str , PromptEvent ) + ' static ,
8270) {
8371 let ( view, doc) = current ! ( cx. editor) ;
@@ -275,13 +263,40 @@ pub mod completers {
275263 use once_cell:: sync:: Lazy ;
276264 use std:: borrow:: Cow ;
277265
278- pub type Completer = fn ( & Editor , & str ) -> Vec < Completion > ;
266+ pub enum CompletionResult {
267+ Immediate ( Vec < Completion > ) ,
268+ Callback ( Box < dyn FnOnce ( ) -> Vec < Completion > + Send + Sync > ) ,
269+ }
270+
271+ fn callback ( f : impl FnOnce ( ) -> Vec < Completion > + Send + Sync + ' static ) -> CompletionResult {
272+ CompletionResult :: Callback ( Box :: new ( f) )
273+ }
274+
275+ impl CompletionResult {
276+ pub fn map (
277+ self ,
278+ f : impl FnOnce ( Vec < Completion > ) -> Vec < Completion > + Send + Sync + ' static ,
279+ ) -> CompletionResult {
280+ match self {
281+ CompletionResult :: Immediate ( v) => CompletionResult :: Immediate ( f ( v) ) ,
282+ CompletionResult :: Callback ( v) => callback ( move || f ( v ( ) ) ) ,
283+ }
284+ }
285+ }
279286
280- pub fn none ( _editor : & Editor , _input : & str ) -> Vec < Completion > {
281- Vec :: new ( )
287+ impl FromIterator < Completion > for CompletionResult {
288+ fn from_iter < T : IntoIterator < Item = Completion > > ( items : T ) -> Self {
289+ Self :: Immediate ( items. into_iter ( ) . collect ( ) )
290+ }
282291 }
283292
284- pub fn buffer ( editor : & Editor , input : & str ) -> Vec < Completion > {
293+ pub type Completer = fn ( & Editor , & str ) -> CompletionResult ;
294+
295+ pub fn none ( _editor : & Editor , _input : & str ) -> CompletionResult {
296+ CompletionResult :: Immediate ( Vec :: new ( ) )
297+ }
298+
299+ pub fn buffer ( editor : & Editor , input : & str ) -> CompletionResult {
285300 let names = editor. documents . values ( ) . map ( |doc| {
286301 doc. relative_path ( )
287302 . map ( |p| p. display ( ) . to_string ( ) . into ( ) )
@@ -294,20 +309,23 @@ pub mod completers {
294309 . collect ( )
295310 }
296311
297- pub fn theme ( _editor : & Editor , input : & str ) -> Vec < Completion > {
298- let mut names = theme:: Loader :: read_names ( & helix_loader:: config_dir ( ) . join ( "themes" ) ) ;
299- for rt_dir in helix_loader:: runtime_dirs ( ) {
300- names. extend ( theme:: Loader :: read_names ( & rt_dir. join ( "themes" ) ) ) ;
301- }
302- names. push ( "default" . into ( ) ) ;
303- names. push ( "base16_default" . into ( ) ) ;
304- names. sort ( ) ;
305- names. dedup ( ) ;
312+ pub fn theme ( _editor : & Editor , input : & str ) -> CompletionResult {
313+ let input = String :: from ( input) ;
314+ callback ( move || {
315+ let mut names = theme:: Loader :: read_names ( & helix_loader:: config_dir ( ) . join ( "themes" ) ) ;
316+ for rt_dir in helix_loader:: runtime_dirs ( ) {
317+ names. extend ( theme:: Loader :: read_names ( & rt_dir. join ( "themes" ) ) ) ;
318+ }
319+ names. push ( "default" . into ( ) ) ;
320+ names. push ( "base16_default" . into ( ) ) ;
321+ names. sort ( ) ;
322+ names. dedup ( ) ;
306323
307- fuzzy_match ( input, names, false )
308- . into_iter ( )
309- . map ( |( name, _) | ( ( 0 ..) , name. into ( ) ) )
310- . collect ( )
324+ fuzzy_match ( & input, names, false )
325+ . into_iter ( )
326+ . map ( |( name, _) | ( ( 0 ..) , name. into ( ) ) )
327+ . collect ( )
328+ } )
311329 }
312330
313331 /// Recursive function to get all keys from this value and add them to vec
@@ -326,7 +344,7 @@ pub mod completers {
326344 }
327345 }
328346
329- pub fn setting ( _editor : & Editor , input : & str ) -> Vec < Completion > {
347+ pub fn setting ( _editor : & Editor , input : & str ) -> CompletionResult {
330348 static KEYS : Lazy < Vec < String > > = Lazy :: new ( || {
331349 let mut keys = Vec :: new ( ) ;
332350 let json = serde_json:: json!( Config :: default ( ) ) ;
@@ -340,27 +358,30 @@ pub mod completers {
340358 . collect ( )
341359 }
342360
343- pub fn filename ( editor : & Editor , input : & str ) -> Vec < Completion > {
361+ pub fn filename ( editor : & Editor , input : & str ) -> CompletionResult {
344362 filename_with_git_ignore ( editor, input, true )
345363 }
346364
347365 pub fn filename_with_git_ignore (
348- editor : & Editor ,
366+ _editor : & Editor ,
349367 input : & str ,
350368 git_ignore : bool ,
351- ) -> Vec < Completion > {
352- filename_impl ( editor, input, git_ignore, |entry| {
353- let is_dir = entry. file_type ( ) . map_or ( false , |entry| entry. is_dir ( ) ) ;
354-
355- if is_dir {
356- FileMatch :: AcceptIncomplete
357- } else {
358- FileMatch :: Accept
359- }
369+ ) -> CompletionResult {
370+ let input = String :: from ( input) ;
371+ callback ( move || {
372+ filename_impl ( & input, git_ignore, |entry| {
373+ let is_dir = entry. file_type ( ) . map_or ( false , |entry| entry. is_dir ( ) ) ;
374+
375+ if is_dir {
376+ FileMatch :: AcceptIncomplete
377+ } else {
378+ FileMatch :: Accept
379+ }
380+ } )
360381 } )
361382 }
362383
363- pub fn language ( editor : & Editor , input : & str ) -> Vec < Completion > {
384+ pub fn language ( editor : & Editor , input : & str ) -> CompletionResult {
364385 let text: String = "text" . into ( ) ;
365386
366387 let loader = editor. syn_loader . load ( ) ;
@@ -375,7 +396,7 @@ pub mod completers {
375396 . collect ( )
376397 }
377398
378- pub fn lsp_workspace_command ( editor : & Editor , input : & str ) -> Vec < Completion > {
399+ pub fn lsp_workspace_command ( editor : & Editor , input : & str ) -> CompletionResult {
379400 let commands = doc ! ( editor)
380401 . language_servers_with_feature ( LanguageServerFeature :: WorkspaceCommand )
381402 . flat_map ( |ls| {
@@ -391,23 +412,26 @@ pub mod completers {
391412 . collect ( )
392413 }
393414
394- pub fn directory ( editor : & Editor , input : & str ) -> Vec < Completion > {
415+ pub fn directory ( editor : & Editor , input : & str ) -> CompletionResult {
395416 directory_with_git_ignore ( editor, input, true )
396417 }
397418
398419 pub fn directory_with_git_ignore (
399- editor : & Editor ,
420+ _editor : & Editor ,
400421 input : & str ,
401422 git_ignore : bool ,
402- ) -> Vec < Completion > {
403- filename_impl ( editor, input, git_ignore, |entry| {
404- let is_dir = entry. file_type ( ) . map_or ( false , |entry| entry. is_dir ( ) ) ;
405-
406- if is_dir {
407- FileMatch :: Accept
408- } else {
409- FileMatch :: Reject
410- }
423+ ) -> CompletionResult {
424+ let input = String :: from ( input) ;
425+ callback ( move || {
426+ filename_impl ( & input, git_ignore, |entry| {
427+ let is_dir = entry. file_type ( ) . map_or ( false , |entry| entry. is_dir ( ) ) ;
428+
429+ if is_dir {
430+ FileMatch :: Accept
431+ } else {
432+ FileMatch :: Reject
433+ }
434+ } )
411435 } )
412436 }
413437
@@ -423,12 +447,7 @@ pub mod completers {
423447 }
424448
425449 // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
426- fn filename_impl < F > (
427- _editor : & Editor ,
428- input : & str ,
429- git_ignore : bool ,
430- filter_fn : F ,
431- ) -> Vec < Completion >
450+ fn filename_impl < F > ( input : & str , git_ignore : bool , filter_fn : F ) -> Vec < Completion >
432451 where
433452 F : Fn ( & ignore:: DirEntry ) -> FileMatch ,
434453 {
@@ -522,7 +541,7 @@ pub mod completers {
522541 }
523542 }
524543
525- pub fn register ( editor : & Editor , input : & str ) -> Vec < Completion > {
544+ pub fn register ( editor : & Editor , input : & str ) -> CompletionResult {
526545 let iter = editor
527546 . registers
528547 . iter_preview ( )
0 commit comments