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
pull/873/head
CossonLeo 3 years ago committed by GitHub
parent a03b12530c
commit 9ac0c95161
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
| `auto-completion` | Enable automatic pop up of auto-completion. | `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` | | `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 ## LSP

@ -235,7 +235,7 @@ impl Application {
} }
pub fn handle_idle_timeout(&mut self) { pub fn handle_idle_timeout(&mut self) {
use crate::commands::{completion, Context}; use crate::commands::{insert::idle_completion, Context};
use helix_view::document::Mode; use helix_view::document::Mode;
if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion { if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
@ -262,7 +262,7 @@ impl Application {
callback: None, callback: None,
on_next_key_callback: None, on_next_key_callback: None,
}; };
completion(&mut cx); idle_completion(&mut cx);
self.render(); self.render();
} }

@ -3308,7 +3308,26 @@ pub mod insert {
pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>; pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;
pub type PostHook = fn(&mut Context, char); 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 // if ch matches completion char, trigger completion
let doc = doc_mut!(cx.editor); let doc = doc_mut!(cx.editor);
let language_server = match doc.language_server() { let language_server = match doc.language_server() {
@ -3318,19 +3337,14 @@ pub mod insert {
let capabilities = language_server.capabilities(); let capabilities = language_server.capabilities();
if let lsp::ServerCapabilities { if let Some(lsp::CompletionOptions {
completion_provider: trigger_characters: Some(triggers),
Some(lsp::CompletionOptions {
trigger_characters: Some(triggers),
..
}),
.. ..
} = capabilities }) = &capabilities.completion_provider
{ {
// TODO: what if trigger is multiple chars long // TODO: what if trigger is multiple chars long
let is_trigger = triggers.iter().any(|trigger| trigger.contains(ch)); if triggers.iter().any(|trigger| trigger.contains(ch)) {
cx.editor.clear_idle_timer();
if is_trigger {
super::completion(cx); super::completion(cx);
} }
} }
@ -3412,7 +3426,8 @@ pub mod insert {
// TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc) // 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 // this could also generically look at Transaction, but it's a bit annoying to look at
// Operation instead of Change. // 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); hook(cx, c);
} }
} }

@ -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. /// 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")] #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
pub idle_timeout: Duration, pub idle_timeout: Duration,
pub completion_trigger_len: u8,
} }
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
@ -87,6 +88,7 @@ impl Default for Config {
auto_pairs: true, auto_pairs: true,
auto_completion: true, auto_completion: true,
idle_timeout: Duration::from_millis(400), idle_timeout: Duration::from_millis(400),
completion_trigger_len: 2,
} }
} }
} }

Loading…
Cancel
Save