on master help sign in
Improve completion trigger (#838)
9ac0c95CossonLeo
book/src/configuration.md+1
@@ -21,6 +21,7 @@ To override global configuration parameters, create a `config.toml` file located
21| `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
21| `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
22| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
22| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
23| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
23| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
24+| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
24
25
25## LSP
26## LSP
26
27
helix-term/src/application.rs+2−2
@@ -235,7 +235,7 @@ impl Application {
235 }
235 }
236
236
237 pub fn handle_idle_timeout(&mut self) {
237 pub fn handle_idle_timeout(&mut self) {
238− use crate::commands::{completion, Context};
238+ use crate::commands::{insert::idle_completion, Context};
239 use helix_view::document::Mode;
239 use helix_view::document::Mode;
240
240
241 if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
241 if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
@@ -262,7 +262,7 @@ impl Application {
262 callback: None,
262 callback: None,
263 on_next_key_callback: None,
263 on_next_key_callback: None,
264 };
264 };
265− completion(&mut cx);
265+ idle_completion(&mut cx);
266 self.render();
266 self.render();
267 }
267 }
268
268
helix-term/src/commands.rs+27−12
@@ -3308,7 +3308,26 @@ pub mod insert {
3308 pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;
3308 pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;
3309 pub type PostHook = fn(&mut Context, char);
3309 pub type PostHook = fn(&mut Context, char);
3310
3310
3311+ // It trigger completion when idle timer reaches deadline
3312+ // Only trigger completion if the word under cursor is longer than n characters
3313+ pub fn idle_completion(cx: &mut Context) {
3314+ let (view, doc) = current!(cx.editor);
3315+ let text = doc.text().slice(..);
3316+ let cursor = doc.selection(view.id).primary().cursor(text);
3317+
3318+ use helix_core::chars::char_is_word;
3319+ let mut iter = text.chars_at(cursor);
3320+ iter.reverse();
3321+ for _ in 0..cx.editor.config.completion_trigger_len {
3322+ match iter.next() {
3323+ Some(c) if char_is_word(c) => {}
3324+ _ => return,
3325+ }
3326+ }
3311− fn completion(cx: &mut Context, ch: char) {
3327+ super::completion(cx);
3328+ }
3329+
3330+ fn language_server_completion(cx: &mut Context, ch: char) {
3312 // if ch matches completion char, trigger completion
3331 // if ch matches completion char, trigger completion
3313 let doc = doc_mut!(cx.editor);
3332 let doc = doc_mut!(cx.editor);
3314 let language_server = match doc.language_server() {
3333 let language_server = match doc.language_server() {
@@ -3318,19 +3337,14 @@ pub mod insert {
3318
3337
3319 let capabilities = language_server.capabilities();
3338 let capabilities = language_server.capabilities();
3320
3339
3321− if let lsp::ServerCapabilities {
3340+ if let Some(lsp::CompletionOptions {
3322− completion_provider:
3323− Some(lsp::CompletionOptions {
3324− trigger_characters: Some(triggers),
3341+ trigger_characters: Some(triggers),
3325− ..
3326− }),
3327 ..
3342 ..
3328− } = capabilities
3343+ }) = &capabilities.completion_provider
3329 {
3344 {
3330 // TODO: what if trigger is multiple chars long
3345 // TODO: what if trigger is multiple chars long
3331− let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch));
3346+ if triggers.iter().any(|trigger| trigger.contains(ch)) {
3332−
3347+ cx.editor.clear_idle_timer();
3333− if is_trigger {
3334 super::completion(cx);
3348 super::completion(cx);
3335 }
3349 }
3336 }
3350 }
@@ -3412,7 +3426,8 @@ pub mod insert {
3412 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
3426 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
3413 // this could also generically look at Transaction, but it's a bit annoying to look at
3427 // this could also generically look at Transaction, but it's a bit annoying to look at
3414 // Operation instead of Change.
3428 // Operation instead of Change.
3415− for hook in &[completion, signature_help] {
3429+ for hook in &[language_server_completion, signature_help] {
3430+ // for hook in &[signature_help] {
3416 hook(cx, c);
3431 hook(cx, c);
3417 }
3432 }
3418 }
3433 }
helix-view/src/editor.rs+2
@@ -58,6 +58,7 @@ pub struct Config {
58 /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
58 /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
59 #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
59 #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
60 pub idle_timeout: Duration,
60 pub idle_timeout: Duration,
61+ pub completion_trigger_len: u8,
61}
62}
62
63
63#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
64#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
@@ -87,6 +88,7 @@ impl Default for Config {
87 auto_pairs: true,
88 auto_pairs: true,
88 auto_completion: true,
89 auto_completion: true,
89 idle_timeout: Duration::from_millis(400),
90 idle_timeout: Duration::from_millis(400),
91+ completion_trigger_len: 2,
90 }
92 }
91 }
93 }
92}
94}