From cd16df19c1f951e1ef0c560ae5e084b18bd2c713 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 23 Dec 2020 17:03:20 +0900 Subject: lsp: generate_transaction_from_text_edits --- Cargo.lock | 11 +++++++++++ helix-lsp/src/lib.rs | 29 +++++++++++++++++++++++++++-- helix-lsp/src/transport.rs | 4 ++-- helix-term/Cargo.toml | 1 + helix-term/src/commands.rs | 17 ++++++++++++++++- 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d94a38b..33b7002a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -594,6 +594,7 @@ dependencies = [ "num_cpus", "once_cell", "smol", + "smol-timeout", "tui", ] @@ -1142,6 +1143,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "smol-timeout" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "847d777e2c6c166bad26264479e80a9820f3d364fcb4a0e23cd57bbfa8e94961" +dependencies = [ + "async-io", + "pin-project-lite", +] + [[package]] name = "socket2" version = "0.3.18" diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index c56721a5..27a5e046 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -28,19 +28,44 @@ pub enum Error { pub mod util { use super::*; + use helix_core::{RopeSlice, State, Transaction}; - pub fn lsp_pos_to_pos(doc: &helix_core::RopeSlice, pos: lsp::Position) -> usize { + pub fn lsp_pos_to_pos(doc: &RopeSlice, pos: lsp::Position) -> usize { let line = doc.line_to_char(pos.line as usize); let line_start = doc.char_to_utf16_cu(line); doc.utf16_cu_to_char(pos.character as usize + line_start) } - pub fn pos_to_lsp_pos(doc: &helix_core::RopeSlice, pos: usize) -> lsp::Position { + pub fn pos_to_lsp_pos(doc: &RopeSlice, pos: usize) -> lsp::Position { let line = doc.char_to_line(pos); let line_start = doc.char_to_utf16_cu(line); let col = doc.char_to_utf16_cu(pos) - line_start; lsp::Position::new(line as u32, col as u32) } + + pub fn generate_transaction_from_edits( + state: &State, + edits: Vec, + ) -> Transaction { + let doc = state.doc.slice(..); + Transaction::change( + state, + edits.into_iter().map(|edit| { + // simplify "" into None for cleaner changesets + let replacement = if !edit.new_text.is_empty() { + Some(edit.new_text.into()) + } else { + None + }; + + let start = lsp_pos_to_pos(&doc, edit.range.start); + let end = lsp_pos_to_pos(&doc, edit.range.end); + (start, end, replacement) + }), + ) + } + + // apply_insert_replace_edit } #[derive(Debug, PartialEq, Clone)] diff --git a/helix-lsp/src/transport.rs b/helix-lsp/src/transport.rs index 22af1b40..07c89fdd 100644 --- a/helix-lsp/src/transport.rs +++ b/helix-lsp/src/transport.rs @@ -107,6 +107,8 @@ impl Transport { // read data + debug!("<- {}", msg); + // try parsing as output (server response) or call (server request) let output: serde_json::Result = serde_json::from_str(&msg); @@ -201,8 +203,6 @@ impl Transport { } let msg = msg.unwrap(); - debug!("<- {:?}", msg); - self.recv_msg(msg).await.unwrap(); } } diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index 645ed155..67e8f443 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -20,6 +20,7 @@ anyhow = "1" once_cell = "1.4" smol = "1" +smol-timeout = "0.6" num_cpus = "1" # tui = { version = "0.12", default-features = false, features = ["crossterm"] } tui = { git = "https://github.com/fdehau/tui-rs", default-features = false, features = ["crossterm"] } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index eb23041c..862cf312 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -837,17 +837,32 @@ pub fn completion(cx: &mut Context) { let language_server = cx.language_servers.get("rust", &cx.executor).unwrap(); use log::info; + use smol_timeout::TimeoutExt; + use std::time::Duration; + // TODO: blocking here is not ideal - let res = smol::block_on(language_server.completion(&cx.view.doc)).expect("completion failed!"); + let res = smol::block_on( + language_server + .completion(&cx.view.doc) + .timeout(Duration::from_secs(2)), + ) + .expect("completion failed!") + .expect("completion failed!"); let picker = ui::Picker::new( res, |item| { // format_fn item.label.as_str().into() + + // TODO: use item.filter_text for filtering }, |editor: &mut Editor, item| { + // if item.text_edit is Some we use that, else + // let insert_text = &item.insert_text.unwrap_or(item.label); + // and we insert at position. // + // merge this with additional_text_edits }, ); -- cgit v1.2.3-70-g09d2