aboutsummaryrefslogtreecommitdiff
path: root/helix-term
diff options
context:
space:
mode:
authorAndrii Grynenko2023-03-03 05:41:06 +0000
committerBlaž Hrastnik2023-03-08 01:48:35 +0000
commit8c2e447b16e4d11db411b18f2fbe3ac2bc031d89 (patch)
treeb0f8684648db275d9b97208fbea92264d776cb1d /helix-term
parent0d924255e4ea3d5d5c4be9b11a337f4316550e32 (diff)
Handle snippets for LSPs not providing offsets for completion
Diffstat (limited to 'helix-term')
-rw-r--r--helix-term/src/ui/completion.rs95
1 files changed, 54 insertions, 41 deletions
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index e7815e12..85931fe3 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -121,8 +121,9 @@ impl Completion {
include_placeholder: bool,
) -> Transaction {
use helix_lsp::snippet;
+ let selection = doc.selection(view_id);
- if let Some(edit) = &item.text_edit {
+ let (start_offset, end_offset, new_text) = if let Some(edit) = &item.text_edit {
let edit = match edit {
lsp::CompletionTextEdit::Edit(edit) => edit.clone(),
lsp::CompletionTextEdit::InsertAndReplace(item) => {
@@ -130,46 +131,27 @@ impl Completion {
lsp::TextEdit::new(item.replace, item.new_text.clone())
}
};
-
- if matches!(item.kind, Some(lsp::CompletionItemKind::SNIPPET))
- || matches!(
- item.insert_text_format,
- Some(lsp::InsertTextFormat::SNIPPET)
- )
- {
- match snippet::parse(&edit.new_text) {
- Ok(snippet) => util::generate_transaction_from_snippet(
- doc.text(),
- doc.selection(view_id),
- &edit.range,
- snippet,
- doc.line_ending.as_str(),
- include_placeholder,
- offset_encoding,
- ),
- Err(err) => {
- log::error!(
- "Failed to parse snippet: {:?}, remaining output: {}",
- &edit.new_text,
- err
- );
- Transaction::new(doc.text())
- }
- }
- } else {
- util::generate_transaction_from_completion_edit(
- doc.text(),
- doc.selection(view_id),
- edit,
- offset_encoding, // TODO: should probably transcode in Client
- )
- }
+ let text = doc.text().slice(..);
+ let primary_cursor = selection.primary().cursor(text);
+
+ let start_offset =
+ match util::lsp_pos_to_pos(doc.text(), edit.range.start, offset_encoding) {
+ Some(start) => start as i128 - primary_cursor as i128,
+ None => return Transaction::new(doc.text()),
+ };
+ let end_offset =
+ match util::lsp_pos_to_pos(doc.text(), edit.range.end, offset_encoding) {
+ Some(end) => end as i128 - primary_cursor as i128,
+ None => return Transaction::new(doc.text()),
+ };
+
+ (start_offset, end_offset, edit.new_text)
} else {
- let text = item.insert_text.as_ref().unwrap_or(&item.label);
+ let new_text = item.insert_text.as_ref().unwrap_or(&item.label);
// Some LSPs just give you an insertText with no offset ¯\_(ツ)_/¯
// in these cases we need to check for a common prefix and remove it
let prefix = Cow::from(doc.text().slice(start_offset..trigger_offset));
- let text = text.trim_start_matches::<&str>(&prefix);
+ let new_text = new_text.trim_start_matches::<&str>(&prefix);
// TODO: this needs to be true for the numbers to work out correctly
// in the closure below. It's passed in to a callback as this same
@@ -182,11 +164,42 @@ impl Completion {
== trigger_offset
);
- Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
- let cursor = range.cursor(doc.text().slice(..));
+ (0, 0, new_text.into())
+ };
- (cursor, cursor, Some(text.into()))
- })
+ if matches!(item.kind, Some(lsp::CompletionItemKind::SNIPPET))
+ || matches!(
+ item.insert_text_format,
+ Some(lsp::InsertTextFormat::SNIPPET)
+ )
+ {
+ match snippet::parse(&new_text) {
+ Ok(snippet) => util::generate_transaction_from_snippet(
+ doc.text(),
+ selection,
+ start_offset,
+ end_offset,
+ snippet,
+ doc.line_ending.as_str(),
+ include_placeholder,
+ ),
+ Err(err) => {
+ log::error!(
+ "Failed to parse snippet: {:?}, remaining output: {}",
+ &new_text,
+ err
+ );
+ Transaction::new(doc.text())
+ }
+ }
+ } else {
+ util::generate_transaction_from_completion_edit(
+ doc.text(),
+ selection,
+ start_offset,
+ end_offset,
+ new_text,
+ )
}
}