@@ -5,7 +5,6 @@ pub(crate) mod typed;
5
5
pub use dap:: * ;
6
6
use helix_vcs:: Hunk ;
7
7
pub use lsp:: * ;
8
- use tokio:: sync:: oneshot;
9
8
use tui:: widgets:: Row ;
10
9
pub use typed:: * ;
11
10
@@ -33,7 +32,7 @@ use helix_core::{
33
32
} ;
34
33
use helix_view:: {
35
34
document:: { FormatterError , Mode , SCRATCH_BUFFER_NAME } ,
36
- editor:: { Action , CompleteAction } ,
35
+ editor:: Action ,
37
36
info:: Info ,
38
37
input:: KeyEvent ,
39
38
keyboard:: KeyCode ,
@@ -52,14 +51,10 @@ use crate::{
52
51
filter_picker_entry,
53
52
job:: Callback ,
54
53
keymap:: ReverseKeymap ,
55
- ui:: {
56
- self , editor:: InsertEvent , lsp:: SignatureHelp , overlay:: overlaid, CompletionItem , Picker ,
57
- Popup , Prompt , PromptEvent ,
58
- } ,
54
+ ui:: { self , overlay:: overlaid, Picker , Popup , Prompt , PromptEvent } ,
59
55
} ;
60
56
61
57
use crate :: job:: { self , Jobs } ;
62
- use futures_util:: { stream:: FuturesUnordered , TryStreamExt } ;
63
58
use std:: { collections:: HashMap , fmt, future:: Future } ;
64
59
use std:: { collections:: HashSet , num:: NonZeroUsize } ;
65
60
@@ -2474,7 +2469,6 @@ fn delete_by_selection_insert_mode(
2474
2469
) ;
2475
2470
}
2476
2471
doc. apply ( & transaction, view. id ) ;
2477
- lsp:: signature_help_impl ( cx, SignatureHelpInvoked :: Automatic ) ;
2478
2472
}
2479
2473
2480
2474
fn delete_selection ( cx : & mut Context ) {
@@ -2548,10 +2542,6 @@ fn insert_mode(cx: &mut Context) {
2548
2542
. transform ( |range| Range :: new ( range. to ( ) , range. from ( ) ) ) ;
2549
2543
2550
2544
doc. set_selection ( view. id , selection) ;
2551
-
2552
- // [TODO] temporary workaround until we're not using the idle timer to
2553
- // trigger auto completions any more
2554
- cx. editor . clear_idle_timer ( ) ;
2555
2545
}
2556
2546
2557
2547
// inserts at the end of each selection
@@ -3374,9 +3364,9 @@ fn hunk_range(hunk: Hunk, text: RopeSlice) -> Range {
3374
3364
3375
3365
pub mod insert {
3376
3366
use crate :: events:: PostInsertChar ;
3367
+
3377
3368
use super :: * ;
3378
3369
pub type Hook = fn ( & Rope , & Selection , char ) -> Option < Transaction > ;
3379
- pub type PostHook = fn ( & mut Context , char ) ;
3380
3370
3381
3371
/// Exclude the cursor in range.
3382
3372
fn exclude_cursor ( text : RopeSlice , range : Range , cursor : Range ) -> Range {
@@ -3390,88 +3380,6 @@ pub mod insert {
3390
3380
}
3391
3381
}
3392
3382
3393
- // It trigger completion when idle timer reaches deadline
3394
- // Only trigger completion if the word under cursor is longer than n characters
3395
- pub fn idle_completion ( cx : & mut Context ) {
3396
- let config = cx. editor . config ( ) ;
3397
- let ( view, doc) = current ! ( cx. editor) ;
3398
- let text = doc. text ( ) . slice ( ..) ;
3399
- let cursor = doc. selection ( view. id ) . primary ( ) . cursor ( text) ;
3400
-
3401
- use helix_core:: chars:: char_is_word;
3402
- let mut iter = text. chars_at ( cursor) ;
3403
- iter. reverse ( ) ;
3404
- for _ in 0 ..config. completion_trigger_len {
3405
- match iter. next ( ) {
3406
- Some ( c) if char_is_word ( c) => { }
3407
- _ => return ,
3408
- }
3409
- }
3410
- super :: completion ( cx) ;
3411
- }
3412
-
3413
- fn language_server_completion ( cx : & mut Context , ch : char ) {
3414
- let config = cx. editor . config ( ) ;
3415
- if !config. auto_completion {
3416
- return ;
3417
- }
3418
-
3419
- use helix_lsp:: lsp;
3420
- // if ch matches completion char, trigger completion
3421
- let doc = doc_mut ! ( cx. editor) ;
3422
- let trigger_completion = doc
3423
- . language_servers_with_feature ( LanguageServerFeature :: Completion )
3424
- . any ( |ls| {
3425
- // TODO: what if trigger is multiple chars long
3426
- matches ! ( & ls. capabilities( ) . completion_provider, Some ( lsp:: CompletionOptions {
3427
- trigger_characters: Some ( triggers) ,
3428
- ..
3429
- } ) if triggers. iter( ) . any( |trigger| trigger. contains( ch) ) )
3430
- } ) ;
3431
-
3432
- if trigger_completion {
3433
- cx. editor . clear_idle_timer ( ) ;
3434
- super :: completion ( cx) ;
3435
- }
3436
- }
3437
-
3438
- fn signature_help ( cx : & mut Context , ch : char ) {
3439
- use helix_lsp:: lsp;
3440
- // if ch matches signature_help char, trigger
3441
- let doc = doc_mut ! ( cx. editor) ;
3442
- // TODO support multiple language servers (not just the first that is found), likely by merging UI somehow
3443
- let Some ( language_server) = doc
3444
- . language_servers_with_feature ( LanguageServerFeature :: SignatureHelp )
3445
- . next ( )
3446
- else {
3447
- return ;
3448
- } ;
3449
-
3450
- let capabilities = language_server. capabilities ( ) ;
3451
-
3452
- if let lsp:: ServerCapabilities {
3453
- signature_help_provider :
3454
- Some ( lsp:: SignatureHelpOptions {
3455
- trigger_characters : Some ( triggers) ,
3456
- // TODO: retrigger_characters
3457
- ..
3458
- } ) ,
3459
- ..
3460
- } = capabilities
3461
- {
3462
- // TODO: what if trigger is multiple chars long
3463
- let is_trigger = triggers. iter ( ) . any ( |trigger| trigger. contains ( ch) ) ;
3464
- // lsp doesn't tell us when to close the signature help, so we request
3465
- // the help information again after common close triggers which should
3466
- // return None, which in turn closes the popup.
3467
- let close_triggers = & [ ')' , ';' , '.' ] ;
3468
-
3469
- if is_trigger || close_triggers. contains ( & ch) {
3470
- super :: signature_help_impl ( cx, SignatureHelpInvoked :: Automatic ) ;
3471
- }
3472
- }
3473
- }
3474
-
3475
3383
// The default insert hook: simply insert the character
3476
3384
#[ allow( clippy:: unnecessary_wraps) ] // need to use Option<> because of the Hook signature
3477
3385
fn insert ( doc : & Rope , selection : & Selection , ch : char ) -> Option < Transaction > {
@@ -3501,12 +3409,6 @@ pub mod insert {
3501
3409
doc. apply ( & t, view. id ) ;
3502
3410
}
3503
3411
3504
- // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
3505
- // this could also generically look at Transaction, but it's a bit annoying to look at
3506
- // Operation instead of Change.
3507
- for hook in & [ language_server_completion, signature_help] {
3508
- hook ( cx, c) ;
3509
- }
3510
3412
helix_event:: dispatch ( PostInsertChar { c, cx } ) ;
3511
3413
}
3512
3414
@@ -3731,8 +3633,6 @@ pub mod insert {
3731
3633
} ) ;
3732
3634
let ( view, doc) = current ! ( cx. editor) ;
3733
3635
doc. apply ( & transaction, view. id ) ;
3734
-
3735
- lsp:: signature_help_impl ( cx, SignatureHelpInvoked :: Automatic ) ;
3736
3636
}
3737
3637
3738
3638
pub fn delete_char_forward ( cx : & mut Context ) {
@@ -4369,151 +4269,7 @@ fn remove_primary_selection(cx: &mut Context) {
4369
4269
}
4370
4270
4371
4271
pub fn completion ( cx : & mut Context ) {
4372
- use helix_lsp:: { lsp, util:: pos_to_lsp_pos} ;
4373
-
4374
- let ( view, doc) = current ! ( cx. editor) ;
4375
-
4376
- let savepoint = if let Some ( CompleteAction :: Selected { savepoint } ) = & cx. editor . last_completion
4377
- {
4378
- savepoint. clone ( )
4379
- } else {
4380
- doc. savepoint ( view)
4381
- } ;
4382
-
4383
- let text = savepoint. text . clone ( ) ;
4384
- let cursor = savepoint. cursor ( ) ;
4385
-
4386
- let mut seen_language_servers = HashSet :: new ( ) ;
4387
-
4388
- let mut futures: FuturesUnordered < _ > = doc
4389
- . language_servers_with_feature ( LanguageServerFeature :: Completion )
4390
- . filter ( |ls| seen_language_servers. insert ( ls. id ( ) ) )
4391
- . map ( |language_server| {
4392
- let language_server_id = language_server. id ( ) ;
4393
- let offset_encoding = language_server. offset_encoding ( ) ;
4394
- let pos = pos_to_lsp_pos ( & text, cursor, offset_encoding) ;
4395
- let doc_id = doc. identifier ( ) ;
4396
- let completion_request = language_server. completion ( doc_id, pos, None ) . unwrap ( ) ;
4397
-
4398
- async move {
4399
- let json = completion_request. await ?;
4400
- let response: Option < lsp:: CompletionResponse > = serde_json:: from_value ( json) ?;
4401
-
4402
- let items = match response {
4403
- Some ( lsp:: CompletionResponse :: Array ( items) ) => items,
4404
- // TODO: do something with is_incomplete
4405
- Some ( lsp:: CompletionResponse :: List ( lsp:: CompletionList {
4406
- is_incomplete : _is_incomplete,
4407
- items,
4408
- } ) ) => items,
4409
- None => Vec :: new ( ) ,
4410
- }
4411
- . into_iter ( )
4412
- . map ( |item| CompletionItem {
4413
- item,
4414
- language_server_id,
4415
- resolved : false ,
4416
- } )
4417
- . collect ( ) ;
4418
-
4419
- anyhow:: Ok ( items)
4420
- }
4421
- } )
4422
- . collect ( ) ;
4423
-
4424
- // setup a channel that allows the request to be canceled
4425
- let ( tx, rx) = oneshot:: channel ( ) ;
4426
- // set completion_request so that this request can be canceled
4427
- // by setting completion_request, the old channel stored there is dropped
4428
- // and the associated request is automatically dropped
4429
- cx. editor . completion_request_handle = Some ( tx) ;
4430
- let future = async move {
4431
- let items_future = async move {
4432
- let mut items = Vec :: new ( ) ;
4433
- // TODO if one completion request errors, all other completion requests are discarded (even if they're valid)
4434
- while let Some ( mut lsp_items) = futures. try_next ( ) . await ? {
4435
- items. append ( & mut lsp_items) ;
4436
- }
4437
- anyhow:: Ok ( items)
4438
- } ;
4439
- tokio:: select! {
4440
- biased;
4441
- _ = rx => {
4442
- Ok ( Vec :: new( ) )
4443
- }
4444
- res = items_future => {
4445
- res
4446
- }
4447
- }
4448
- } ;
4449
-
4450
- let trigger_offset = cursor;
4451
-
4452
- // TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
4453
- // completion filtering. For example logger.te| should filter the initial suggestion list with "te".
4454
-
4455
- use helix_core:: chars;
4456
- let mut iter = text. chars_at ( cursor) ;
4457
- iter. reverse ( ) ;
4458
- let offset = iter. take_while ( |ch| chars:: char_is_word ( * ch) ) . count ( ) ;
4459
- let start_offset = cursor. saturating_sub ( offset) ;
4460
-
4461
- let trigger_doc = doc. id ( ) ;
4462
- let trigger_view = view. id ;
4463
-
4464
- // FIXME: The commands Context can only have a single callback
4465
- // which means it gets overwritten when executing keybindings
4466
- // with multiple commands or macros. This would mean that completion
4467
- // might be incorrectly applied when repeating the insertmode action
4468
- //
4469
- // TODO: to solve this either make cx.callback a Vec of callbacks or
4470
- // alternatively move `last_insert` to `helix_view::Editor`
4471
- cx. callback = Some ( Box :: new (
4472
- move |compositor : & mut Compositor , _cx : & mut compositor:: Context | {
4473
- let ui = compositor. find :: < ui:: EditorView > ( ) . unwrap ( ) ;
4474
- ui. last_insert . 1 . push ( InsertEvent :: RequestCompletion ) ;
4475
- } ,
4476
- ) ) ;
4477
-
4478
- cx. jobs . callback ( async move {
4479
- let items = future. await ?;
4480
- let call = move |editor : & mut Editor , compositor : & mut Compositor | {
4481
- let ( view, doc) = current_ref ! ( editor) ;
4482
- // check if the completion request is stale.
4483
- //
4484
- // Completions are completed asynchronously and therefore the user could
4485
- //switch document/view or leave insert mode. In all of thoise cases the
4486
- // completion should be discarded
4487
- if editor. mode != Mode :: Insert || view. id != trigger_view || doc. id ( ) != trigger_doc {
4488
- return ;
4489
- }
4490
-
4491
- if items. is_empty ( ) {
4492
- // editor.set_error("No completion available");
4493
- return ;
4494
- }
4495
- let size = compositor. size ( ) ;
4496
- let ui = compositor. find :: < ui:: EditorView > ( ) . unwrap ( ) ;
4497
- let completion_area = ui. set_completion (
4498
- editor,
4499
- savepoint,
4500
- items,
4501
- start_offset,
4502
- trigger_offset,
4503
- size,
4504
- ) ;
4505
- let size = compositor. size ( ) ;
4506
- let signature_help_area = compositor
4507
- . find_id :: < Popup < SignatureHelp > > ( SignatureHelp :: ID )
4508
- . map ( |signature_help| signature_help. area ( size, editor) ) ;
4509
- // Delete the signature help popup if they intersect.
4510
- if matches ! ( ( completion_area, signature_help_area) , ( Some ( a) , Some ( b) ) if a. intersects( b) )
4511
- {
4512
- compositor. remove ( SignatureHelp :: ID ) ;
4513
- }
4514
- } ;
4515
- Ok ( Callback :: EditorCompositor ( Box :: new ( call) ) )
4516
- } ) ;
4272
+ cx. editor . handlers . trigger_completions ( ) ;
4517
4273
}
4518
4274
4519
4275
// comments
@@ -4692,10 +4448,6 @@ fn move_node_bound_impl(cx: &mut Context, dir: Direction, movement: Movement) {
4692
4448
) ;
4693
4449
4694
4450
doc. set_selection ( view. id , selection) ;
4695
-
4696
- // [TODO] temporary workaround until we're not using the idle timer to
4697
- // trigger auto completions any more
4698
- editor. clear_idle_timer ( ) ;
4699
4451
}
4700
4452
} ;
4701
4453
0 commit comments