From 764d14f55894dc7213e48022dfa0f91829b8ef59 Mon Sep 17 00:00:00 2001 From: farwyler <1705805+farwyler@users.noreply.github.com> Date: Wed, 15 Jun 2022 10:00:27 +0200 Subject: [PATCH] redetect indent and line endings after language server replaces document --- helix-lsp/src/lib.rs | 29 +++++++++++++++++++++++++++++ helix-term/src/commands.rs | 15 +++++++++++---- helix-view/src/document.rs | 7 ++++++- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 6a5f9d5ca4f7b..e02086ffcad7a 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -221,6 +221,35 @@ pub mod util { generate_transaction_from_edits(&fmt.doc, fmt.edits, fmt.offset_encoding) } } + + impl LspFormatting { + pub fn replaces_document(&self, old: &Rope) -> Option<&String> { + match &self.edits[..] { + [lsp::TextEdit { + range: + lsp::Range { + start: + lsp::Position { + line: 0, + character: 0, + }, + end: + lsp::Position { + line: last_line, .. + }, + }, + new_text, + }] => { + if *last_line as usize >= old.len_lines() - 1 { + Some(new_text) + } else { + None + } + } + _ => None, + } + } + } } #[derive(Debug, PartialEq, Clone)] diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c9c8e6a98c623..6cd6287832f5e 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2326,10 +2326,17 @@ async fn make_format_callback( let view_id = view!(editor).id; if let Some(doc) = editor.document_mut(doc_id) { if doc.version() == doc_version { - doc.apply(&Transaction::from(format), view_id); - doc.append_changes_to_history(view_id); - if let Modified::SetUnmodified = modified { - doc.reset_modified(); + if let Some(text) = format.replaces_document(doc.text()) { + // the language server wants to replace the whole document. perform same behaviour as if reloading document from disk. + log::info!("formatting changes replace the whole document"); + let rope = Rope::from_str(text); + doc.replace_content(view_id, &rope).unwrap(); + } else { + doc.apply(&Transaction::from(format), view_id); + doc.append_changes_to_history(view_id); + if let Modified::SetUnmodified = modified { + doc.reset_modified(); + } } } else { log::info!("discarded formatting changes because the document changed"); diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index a2d2af77c0201..432b4a33154aa 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -549,10 +549,15 @@ impl Document { let mut file = std::fs::File::open(path.unwrap())?; let (rope, ..) = from_reader(&mut file, Some(encoding))?; + self.replace_content(view_id, &rope) + } + + /// Replace the whole text. + pub fn replace_content(&mut self, view_id: ViewId, rope: &Rope) -> Result<(), Error> { // Calculate the difference between the buffer and source text, and apply it. // This is not considered a modification of the contents of the file regardless // of the encoding. - let transaction = helix_core::diff::compare_ropes(self.text(), &rope); + let transaction = helix_core::diff::compare_ropes(self.text(), rope); self.apply(&transaction, view_id); self.append_changes_to_history(view_id); self.reset_modified();