From 8e592a151fe7adfbf3fb35ae134b7f2a70700f09 Mon Sep 17 00:00:00 2001 From: Pascal Kuthe Date: Fri, 1 Dec 2023 00:03:27 +0100 Subject: refactor completion and signature help using hooks --- helix-view/src/document.rs | 14 -------------- helix-view/src/editor.rs | 35 ++++++++++++++++++----------------- helix-view/src/handlers.rs | 37 +++++++++++++++++++++++++++++++++---- helix-view/src/handlers/lsp.rs | 35 ++++++++++++++++++----------------- 4 files changed, 69 insertions(+), 52 deletions(-) (limited to 'helix-view/src') diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 93b83da4..388810b1 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -115,19 +115,6 @@ pub struct SavePoint { /// The view this savepoint is associated with pub view: ViewId, revert: Mutex, - pub text: Rope, -} - -impl SavePoint { - pub fn cursor(&self) -> usize { - // we always create transactions with selections - self.revert - .lock() - .selection() - .unwrap() - .primary() - .cursor(self.text.slice(..)) - } } pub struct Document { @@ -1404,7 +1391,6 @@ impl Document { let savepoint = Arc::new(SavePoint { view: view.id, revert: Mutex::new(revert), - text: self.text.clone(), }); self.savepoints.push(Arc::downgrade(&savepoint)); savepoint diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 44c706d7..dc10a604 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -31,10 +31,7 @@ use std::{ }; use tokio::{ - sync::{ - mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, - oneshot, - }, + sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, time::{sleep, Duration, Instant, Sleep}, }; @@ -244,12 +241,19 @@ pub struct Config { /// Set a global text_width pub text_width: usize, /// Time in milliseconds since last keypress before idle timers trigger. - /// Used for autocompletion, set to 0 for instant. Defaults to 250ms. + /// Used for various UI timeouts. Defaults to 250ms. #[serde( serialize_with = "serialize_duration_millis", deserialize_with = "deserialize_duration_millis" )] pub idle_timeout: Duration, + /// Time in milliseconds after typing a word character before auto completions + /// are shown, set to 5 for instant. Defaults to 250ms. + #[serde( + serialize_with = "serialize_duration_millis", + deserialize_with = "deserialize_duration_millis" + )] + pub completion_timeout: Duration, /// Whether to insert the completion suggestion on hover. Defaults to true. pub preview_completion_insert: bool, pub completion_trigger_len: u8, @@ -829,6 +833,7 @@ impl Default for Config { auto_format: true, auto_save: false, idle_timeout: Duration::from_millis(250), + completion_timeout: Duration::from_millis(250), preview_completion_insert: true, completion_trigger_len: 2, auto_info: true, @@ -953,14 +958,6 @@ pub struct Editor { /// avoid calculating the cursor position multiple /// times during rendering and should not be set by other functions. pub cursor_cache: Cell>>, - /// When a new completion request is sent to the server old - /// unfinished request must be dropped. Each completion - /// request is associated with a channel that cancels - /// when the channel is dropped. That channel is stored - /// here. When a new completion request is sent this - /// field is set and any old requests are automatically - /// canceled as a result - pub completion_request_handle: Option>, pub handlers: Handlers, } @@ -989,13 +986,16 @@ enum ThemeAction { #[derive(Debug, Clone)] pub enum CompleteAction { + Triggered, + /// A savepoint of the currently selected completion. The savepoint + /// MUST be restored before sending any event to the LSP + Selected { + savepoint: Arc, + }, Applied { trigger_offset: usize, changes: Vec, }, - /// A savepoint of the currently selected completion. The savepoint - /// MUST be restored before sending any event to the LSP - Selected { savepoint: Arc }, } #[derive(Debug, Copy, Clone)] @@ -1029,6 +1029,7 @@ impl Editor { theme_loader: Arc, syn_loader: Arc, config: Arc>, + handlers: Handlers, ) -> Self { let language_servers = helix_lsp::Registry::new(syn_loader.clone()); let conf = config.load(); @@ -1073,7 +1074,7 @@ impl Editor { config_events: unbounded_channel(), needs_redraw: false, cursor_cache: Cell::new(None), - completion_request_handle: None, + handlers, } } diff --git a/helix-view/src/handlers.rs b/helix-view/src/handlers.rs index ae3eb545..724e7b19 100644 --- a/helix-view/src/handlers.rs +++ b/helix-view/src/handlers.rs @@ -1,12 +1,41 @@ -use std::sync::Arc; - use helix_event::send_blocking; use tokio::sync::mpsc::Sender; use crate::handlers::lsp::SignatureHelpInvoked; -use crate::Editor; +use crate::{DocumentId, Editor, ViewId}; pub mod dap; pub mod lsp; -pub struct Handlers {} +pub struct Handlers { + // only public because most of the actual implementation is in helix-term right now :/ + pub completions: Sender, + pub signature_hints: Sender, +} + +impl Handlers { + /// Manually trigger completion (c-x) + pub fn trigger_completions(&self, trigger_pos: usize, doc: DocumentId, view: ViewId) { + send_blocking( + &self.completions, + lsp::CompletionEvent::ManualTrigger { + cursor: trigger_pos, + doc, + view, + }, + ); + } + + pub fn trigger_signature_help(&self, invocation: SignatureHelpInvoked, editor: &Editor) { + let event = match invocation { + SignatureHelpInvoked::Automatic => { + if !editor.config().lsp.auto_signature_help { + return; + } + lsp::SignatureHelpEvent::Trigger + } + SignatureHelpInvoked::Manual => lsp::SignatureHelpEvent::Invoked, + }; + send_blocking(&self.signature_hints, event) + } +} diff --git a/helix-view/src/handlers/lsp.rs b/helix-view/src/handlers/lsp.rs index 95838564..1dae45dd 100644 --- a/helix-view/src/handlers/lsp.rs +++ b/helix-view/src/handlers/lsp.rs @@ -1,26 +1,27 @@ use crate::{DocumentId, ViewId}; -#[derive(Debug, Clone, Copy)] -pub struct CompletionTrigger { - /// The char position of the primary cursor when the - /// completion was triggered - pub trigger_pos: usize, - pub doc: DocumentId, - pub view: ViewId, - /// Whether the cause of the trigger was an automatic completion (any word - /// char for words longer than minimum word length). - /// This is false for trigger chars send by the LS - pub auto: bool, -} - pub enum CompletionEvent { /// Auto completion was triggered by typing a word char - /// or a completion trigger - Trigger(CompletionTrigger), + AutoTrigger { + cursor: usize, + doc: DocumentId, + view: ViewId, + }, + /// Auto completion was triggered by typing a trigger char + /// specified by the LSP + TriggerChar { + cursor: usize, + doc: DocumentId, + view: ViewId, + }, /// A completion was manually requested (c-x) - Manual, + ManualTrigger { + cursor: usize, + doc: DocumentId, + view: ViewId, + }, /// Some text was deleted and the cursor is now at `pos` - DeleteText { pos: usize }, + DeleteText { cursor: usize }, /// Invalidate the current auto completion trigger Cancel, } -- cgit v1.2.3-70-g09d2