mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-12-01 19:58:12 +03:00
allow LSP insert text to replace non-matching prefixes (#5469)
Most LSPs will complete case-insensitive matches, particularly from lowercase to uppercase. In some cases, notably Pyright, this is given as a simple insert text instead of TextEdit. When this happens, the prefix text was left unedited.
This commit is contained in:
parent
ce1fb9e64c
commit
9b4326b18b
@ -124,6 +124,8 @@ impl Completion {
|
|||||||
) -> Transaction {
|
) -> Transaction {
|
||||||
use helix_lsp::snippet;
|
use helix_lsp::snippet;
|
||||||
let selection = doc.selection(view_id);
|
let selection = doc.selection(view_id);
|
||||||
|
let text = doc.text().slice(..);
|
||||||
|
let primary_cursor = selection.primary().cursor(text);
|
||||||
|
|
||||||
let (start_offset, end_offset, new_text) = 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 {
|
let edit = match edit {
|
||||||
@ -133,8 +135,6 @@ impl Completion {
|
|||||||
lsp::TextEdit::new(item.replace, item.new_text.clone())
|
lsp::TextEdit::new(item.replace, item.new_text.clone())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let text = doc.text().slice(..);
|
|
||||||
let primary_cursor = selection.primary().cursor(text);
|
|
||||||
|
|
||||||
let start_offset =
|
let start_offset =
|
||||||
match util::lsp_pos_to_pos(doc.text(), edit.range.start, offset_encoding) {
|
match util::lsp_pos_to_pos(doc.text(), edit.range.start, offset_encoding) {
|
||||||
@ -149,24 +149,26 @@ impl Completion {
|
|||||||
|
|
||||||
(start_offset, end_offset, edit.new_text)
|
(start_offset, end_offset, edit.new_text)
|
||||||
} else {
|
} else {
|
||||||
let new_text = item.insert_text.as_ref().unwrap_or(&item.label);
|
let new_text = item
|
||||||
// Some LSPs just give you an insertText with no offset ¯\_(ツ)_/¯
|
.insert_text
|
||||||
// in these cases we need to check for a common prefix and remove it
|
.clone()
|
||||||
let prefix = Cow::from(doc.text().slice(start_offset..trigger_offset));
|
.unwrap_or_else(|| item.label.clone());
|
||||||
let new_text = new_text.trim_start_matches::<&str>(&prefix);
|
|
||||||
|
|
||||||
// TODO: this needs to be true for the numbers to work out correctly
|
// check that we are still at the correct savepoint
|
||||||
// in the closure below. It's passed in to a callback as this same
|
// we can still generate a transaction regardless but if the
|
||||||
// formula, but can the value change between the LSP request and
|
// document changed (and not just the selection) then we will
|
||||||
// response? If it does, can we recover?
|
// likely delete the wrong text (same if we applied an edit sent by the LS)
|
||||||
debug_assert!(
|
debug_assert!(primary_cursor == trigger_offset);
|
||||||
doc.selection(view_id)
|
|
||||||
.primary()
|
|
||||||
.cursor(doc.text().slice(..))
|
|
||||||
== trigger_offset
|
|
||||||
);
|
|
||||||
|
|
||||||
(0, 0, new_text.into())
|
// TODO: Respect editor.completion_replace?
|
||||||
|
// Would require detecting the end of the word boundary for every cursor individually.
|
||||||
|
// We don't do the same for normal `edits, to be consistent we would have to do it for those too
|
||||||
|
|
||||||
|
(
|
||||||
|
start_offset as i128 - primary_cursor as i128,
|
||||||
|
trigger_offset as i128 - primary_cursor as i128,
|
||||||
|
new_text,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches!(item.kind, Some(lsp::CompletionItemKind::SNIPPET))
|
if matches!(item.kind, Some(lsp::CompletionItemKind::SNIPPET))
|
||||||
|
Loading…
Reference in New Issue
Block a user