aboutsummaryrefslogtreecommitdiff
path: root/helix-lsp/src/lib.rs
diff options
context:
space:
mode:
authorMichael Davis2022-12-06 01:29:40 +0000
committerGitHub2022-12-06 01:29:40 +0000
commit2077f5e26a4cdaadde4b505fc64eadb9e6849c0d (patch)
treeb3b274e5efcc12cbe57b090d08d590aceab833f2 /helix-lsp/src/lib.rs
parent7210c58a51a16c0ae3c9d77211ed1a25e039bd9e (diff)
Apply completion edits to all cursors (#4496)
Completion edits - either basic `insert_text` strings or structured `text_edit`s - are assumed by the LSP spec to apply to the current cursor (or at least the trigger point). We can use the range (if any) and text given by the Language Server to create a transaction that changes all ranges in the current selection though, allowing auto- complete to affect multiple cursors.
Diffstat (limited to 'helix-lsp/src/lib.rs')
-rw-r--r--helix-lsp/src/lib.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index abc930f8..f714395f 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -57,7 +57,7 @@ pub enum OffsetEncoding {
pub mod util {
use super::*;
- use helix_core::{diagnostic::NumberOrString, Range, Rope, Transaction};
+ use helix_core::{diagnostic::NumberOrString, Range, Rope, Selection, Tendril, Transaction};
/// Converts a diagnostic in the document to [`lsp::Diagnostic`].
///
@@ -196,6 +196,42 @@ pub mod util {
Some(Range::new(start, end))
}
+ /// Creates a [Transaction] from the [lsp::TextEdit] in a completion response.
+ /// The transaction applies the edit to all cursors.
+ pub fn generate_transaction_from_completion_edit(
+ doc: &Rope,
+ selection: &Selection,
+ edit: lsp::TextEdit,
+ offset_encoding: OffsetEncoding,
+ ) -> Transaction {
+ let replacement: Option<Tendril> = if edit.new_text.is_empty() {
+ None
+ } else {
+ Some(edit.new_text.into())
+ };
+
+ let text = doc.slice(..);
+ let primary_cursor = selection.primary().cursor(text);
+
+ let start_offset = match lsp_pos_to_pos(doc, edit.range.start, offset_encoding) {
+ Some(start) => start as i128 - primary_cursor as i128,
+ None => return Transaction::new(doc),
+ };
+ let end_offset = match lsp_pos_to_pos(doc, edit.range.end, offset_encoding) {
+ Some(end) => end as i128 - primary_cursor as i128,
+ None => return Transaction::new(doc),
+ };
+
+ Transaction::change_by_selection(doc, selection, |range| {
+ let cursor = range.cursor(text);
+ (
+ (cursor as i128 + start_offset) as usize,
+ (cursor as i128 + end_offset) as usize,
+ replacement.clone(),
+ )
+ })
+ }
+
pub fn generate_transaction_from_edits(
doc: &Rope,
mut edits: Vec<lsp::TextEdit>,