From 9ac0c951615d624041836cdd7afd869391c72fff Mon Sep 17 00:00:00 2001 From: CossonLeo <20379044+cossonleo@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:14:50 +0800 Subject: [PATCH] Improve completion trigger (#838) * improve idle completion trigger * add completion-trigger-len to book * rename semantics_completion to language_server_completion and optimize idle completion trigger --- book/src/configuration.md | 1 + helix-term/src/application.rs | 4 ++-- helix-term/src/commands.rs | 39 ++++++++++++++++++++++++----------- helix-view/src/editor.rs | 2 ++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index d47f95d91..7d6ff28f8 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -21,6 +21,7 @@ To override global configuration parameters, create a `config.toml` file located | `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` | | `auto-completion` | Enable automatic pop up of auto-completion. | `true` | | `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` | +| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` | ## LSP diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 0e7d0e558..a7281ecf6 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -235,7 +235,7 @@ impl Application { } pub fn handle_idle_timeout(&mut self) { - use crate::commands::{completion, Context}; + use crate::commands::{insert::idle_completion, Context}; use helix_view::document::Mode; if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion { @@ -262,7 +262,7 @@ impl Application { callback: None, on_next_key_callback: None, }; - completion(&mut cx); + idle_completion(&mut cx); self.render(); } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 95c46a4ed..2811f293a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -3308,7 +3308,26 @@ pub mod insert { pub type Hook = fn(&Rope, &Selection, char) -> Option; pub type PostHook = fn(&mut Context, char); - fn completion(cx: &mut Context, ch: char) { + // It trigger completion when idle timer reaches deadline + // Only trigger completion if the word under cursor is longer than n characters + pub fn idle_completion(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); + let cursor = doc.selection(view.id).primary().cursor(text); + + use helix_core::chars::char_is_word; + let mut iter = text.chars_at(cursor); + iter.reverse(); + for _ in 0..cx.editor.config.completion_trigger_len { + match iter.next() { + Some(c) if char_is_word(c) => {} + _ => return, + } + } + super::completion(cx); + } + + fn language_server_completion(cx: &mut Context, ch: char) { // if ch matches completion char, trigger completion let doc = doc_mut!(cx.editor); let language_server = match doc.language_server() { @@ -3318,19 +3337,14 @@ pub mod insert { let capabilities = language_server.capabilities(); - if let lsp::ServerCapabilities { - completion_provider: - Some(lsp::CompletionOptions { - trigger_characters: Some(triggers), - .. - }), + if let Some(lsp::CompletionOptions { + trigger_characters: Some(triggers), .. - } = capabilities + }) = &capabilities.completion_provider { // TODO: what if trigger is multiple chars long - let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch)); - - if is_trigger { + if triggers.iter().any(|trigger| trigger.contains(ch)) { + cx.editor.clear_idle_timer(); super::completion(cx); } } @@ -3412,7 +3426,8 @@ pub mod insert { // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc) // this could also generically look at Transaction, but it's a bit annoying to look at // Operation instead of Change. - for hook in &[completion, signature_help] { + for hook in &[language_server_completion, signature_help] { + // for hook in &[signature_help] { hook(cx, c); } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 90e3bf471..52fca6d25 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -58,6 +58,7 @@ pub struct Config { /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms. #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")] pub idle_timeout: Duration, + pub completion_trigger_len: u8, } #[derive(Debug, Clone, PartialEq, Eq, Deserialize)] @@ -87,6 +88,7 @@ impl Default for Config { auto_pairs: true, auto_completion: true, idle_timeout: Duration::from_millis(400), + completion_trigger_len: 2, } } }