From b1f75280909884c9621b553b43030ac39cfa47ce Mon Sep 17 00:00:00 2001 From: Pascal Kuthe Date: Thu, 9 Mar 2023 23:08:55 +0100 Subject: fix snippet bugs and multicursor completion edgecases Multicursor completions may overlap and therefore overlapping completions must be dropped to avoid crashes. Furthermore, multicursor edits might simply be out of range if the word before/after the cursor is shorter. This currently leads to crashes, instead these selections are now also removed for completions. This commit also significantly refactors snippet transaction generation so that tabstops behave correctly with the above rules. Furthermore, snippet tabstops need to be carefully mapped to ensure their position is correct and consistent with our selection semantics. Finally, we now keep a partially updated Rope while creating snippet transactions so that we can fill information into snippets that depends on the position in the document. --- helix-term/src/ui/completion.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'helix-term/src/ui') diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index 336b75cb..99c33781 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -118,7 +118,6 @@ impl Completion { view_id: ViewId, item: &CompletionItem, offset_encoding: helix_lsp::OffsetEncoding, - start_offset: usize, trigger_offset: usize, include_placeholder: bool, ) -> Transaction { @@ -147,28 +146,18 @@ impl Completion { None => return Transaction::new(doc.text()), }; - (start_offset, end_offset, edit.new_text) + (Some((start_offset, end_offset)), edit.new_text) } else { let new_text = item .insert_text .clone() .unwrap_or_else(|| item.label.clone()); - // check that we are still at the correct savepoint // we can still generate a transaction regardless but if the // document changed (and not just the selection) then we will // likely delete the wrong text (same if we applied an edit sent by the LS) debug_assert!(primary_cursor == trigger_offset); - - // 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, - ) + (None, Some(0), new_text) }; if matches!(item.kind, Some(lsp::CompletionItemKind::SNIPPET)) @@ -186,6 +175,7 @@ impl Completion { snippet, doc.line_ending.as_str(), include_placeholder, + doc.tab_width(), ), Err(err) => { log::error!( @@ -232,7 +222,6 @@ impl Completion { view.id, item, offset_encoding, - start_offset, trigger_offset, true, ); @@ -254,7 +243,6 @@ impl Completion { view.id, item, offset_encoding, - start_offset, trigger_offset, false, ); -- cgit v1.2.3-70-g09d2