A simple CPU rendered GUI IDE experience.
handle the weird wsedits
| -rw-r--r-- | src/edi/input_handlers/keyboard.rs | 16 | ||||
| -rw-r--r-- | src/edi/wsedit.rs | 73 | ||||
| -rw-r--r-- | src/hov.rs | 3 | ||||
| -rw-r--r-- | src/text.rs | 23 |
4 files changed, 73 insertions, 42 deletions
diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs index 351e323..bfc901e 100644 --- a/src/edi/input_handlers/keyboard.rs +++ b/src/edi/input_handlers/keyboard.rs @@ -280,10 +280,8 @@ impl Editor { match x { Ok(Some(x)) => - if let Err(e) = - self.apply_wsedit(x, &f.to_owned()) - { - println!( + if let Err(e) = self.apply_wsedit(x) { + log::error!( "couldnt apply one or more wsedits: \ {e}" ); @@ -345,9 +343,7 @@ impl Editor { c.left(); } Some(Do::CASelectRight) => 'out: { - let Some((lsp, f)) = lsp!(self + p) else { - unreachable!() - }; + let Some(lsp) = lsp!(self) else { unreachable!() }; let State::CodeAction(Rq { result: Some(c), .. }) = &mut self.state else { @@ -361,9 +357,8 @@ impl Editor { let act = lsp .request_immediate::<CodeActionResolveRequest>(&act) .unwrap(); - let f = f.to_owned(); if let Some(x) = act.edit - && let Err(e) = self.apply_wsedit(x, &f) + && let Err(e) = self.apply_wsedit(x) { log::error!("{e}"); } @@ -553,11 +548,12 @@ impl Editor { else { panic!() }; + use ttools::OptionOfMutRefToTuple; *x = Some(( h, c.as_ref() .map(|x| x.start) - .or(x.as_ref().map(|x| x.1)) + .or(x.on::<1>().copied()) .unwrap_or(*self.text.cursor.first()), )); } diff --git a/src/edi/wsedit.rs b/src/edi/wsedit.rs index c4f327c..ae87476 100644 --- a/src/edi/wsedit.rs +++ b/src/edi/wsedit.rs @@ -8,54 +8,65 @@ use ropey::Rope; use super::*; use crate::error::WDebug; -use crate::lsp::PathURI; +use crate::lsp::Void; use crate::text::{SortTedits, TextArea}; impl Editor { - fn apply_tde( + fn apply_tds<T>( &mut self, - TextDocumentEdit { - mut edits, - text_document, - .. - }: TextDocumentEdit, - f: &Path, - ) -> rootcause::Result<()> { + to: &Path, + mut edits: Vec<T>, + mut apply: impl FnMut(&mut TextArea, &T) -> rootcause::Result<()>, + mut apply2: impl FnMut(&T, &mut Rope) -> rootcause::Result<()>, + ) -> rootcause::Result<()> + where + [T]: SortTedits, + { edits.sort_tedits(); - if text_document.uri != f.tid().uri { + if Some(to) != self.origin.as_deref() { let f = OpenOptions::new() .read(true) .create(true) .write(true) - .open(text_document.uri.path())?; + .open(to)?; let mut r = Rope::from_reader(f)?; let () = edits .iter() - .map(|x| TextArea::apply_snippet_tedit_raw(x, &mut r)) + .map(|x| apply2(x, &mut r)) .collect_reports() .context("applying one or more snippet tedits failed")?; r.write_to( - OpenOptions::new() - .write(true) - .truncate(true) - .open(text_document.uri.path())?, + OpenOptions::new().write(true).truncate(true).open(to)?, )?; } else { let () = edits .iter() - .map(|x| self.text.apply_snippet_tedit(x)) + .map(|x| apply(&mut self.text, x)) .collect_reports() .context("applying one or more sneddits failed")?; } Ok(()) } + fn apply_tde( + &mut self, + TextDocumentEdit { edits, text_document, .. }: TextDocumentEdit, + ) -> rootcause::Result<()> { + self.apply_tds( + &text_document + .uri + .to_file_path() + .map_err(|_| report!("sad"))?, + edits, + TextArea::apply_snippet_tedit, + TextArea::apply_snippet_tedit_raw, + ) + } fn apply_dco( &mut self, op: DocumentChangeOperation, - f: &Path, ) -> rootcause::Result<()> { match op.clone() { - DocumentChangeOperation::Edit(t) => self.apply_tde(t, f)?, + DocumentChangeOperation::Edit(t) => self.apply_tde(t)?, DocumentChangeOperation::Op(ResourceOp::Create( CreateFile { uri, options, .. }, )) => { @@ -198,7 +209,6 @@ impl Editor { pub fn apply_wsedit( &mut self, x: WorkspaceEdit, - f: &Path, ) -> rootcause::Result<()> { match x { WorkspaceEdit { @@ -206,7 +216,7 @@ impl Editor { .. } => x .into_iter() - .map(|x| self.apply_tde(x, f)) + .map(|x| self.apply_tde(x)) .collect_reports() .context("couldnt apply one or more wsedits")?, WorkspaceEdit { @@ -216,15 +226,28 @@ impl Editor { .clone() .into_iter() .map(|op: DocumentChangeOperation| { - self.apply_dco(op.clone(), f) + self.apply_dco(op.clone()) .context_custom::<WDebug, _>(op) }) .collect_reports() .context("couldnt apply one or more fs operations") .context_custom::<WDebug, _>(x)?, - WorkspaceEdit { changes: Some(x), .. } => - do yeet report!("we dont handle these kinds of changes") - .context_custom::<WDebug, _>(x), + WorkspaceEdit { changes: Some(x), .. } => x + .into_iter() + .map(|(p, e)| { + self.apply_tds( + &p.to_file_path().map_err(|_| { + report!("evil path") + .context_custom::<WDebug, _>(e.clone()) + })?, + e.clone(), + |x, y| x.apply(y).map(drop), + TextArea::apply_raw, + ) + .context_custom::<WDebug, _>(e) + }) + .collect_reports() + .context("couldnt apply one or more fs operations")?, x => do yeet report!("strange workspace edit") .context_custom::<WDebug, _>(x), @@ -8,6 +8,7 @@ use itertools::Itertools; use markdown::mdast::{self, Node}; use ropey::Rope; use serde_derive::{Deserialize, Serialize}; +use ttools::{IteratorOfTuples, IteratorOfTuplesWithF}; const D: Cell = Cell { letter: None, style: Style::new(FG, BG) }; use crate::{FG, text}; @@ -221,7 +222,7 @@ pub fn l(node: &Node) -> Vec<usize> { .into_iter() .chunk_by(|&x| x != usize::MAX) .into_iter() - .filter_map(|x| x.0.then(|| x.1.sum::<usize>())) + .filter_map(|(b, g)| b.then(|| g.sum::<usize>())) .collect::<Vec<_>>() } #[implicit_fn::implicit_fn] diff --git a/src/text.rs b/src/text.rs index 8f644e0..912feae 100644 --- a/src/text.rs +++ b/src/text.rs @@ -462,6 +462,17 @@ impl TextArea { self.insert_at(begin, &x.new_text)?; Ok((begin, end)) } + pub fn apply_raw<'a, 'b>( + x: &'a TextEdit, + r: &'b mut Rope, + ) -> rootcause::Result<()> { + let begin = + r.l_position(x.range.start).ok_or(report!("no range"))?; + let end = r.l_position(x.range.end).ok_or(report!("no range"))?; + r.try_remove(begin..end)?; + r.try_insert(begin, &x.new_text)?; + Ok(()) + } pub fn apply_adjusting( &mut self, @@ -482,9 +493,9 @@ impl TextArea { } Ok(()) } - pub fn apply_snippet_tedit_raw( - SnippetTextEdit { range,new_text, insert_text_format, .. }: &SnippetTextEdit, - text: &'_ mut Rope, + pub fn apply_snippet_tedit_raw<'a, 'b>( + SnippetTextEdit { range,new_text, insert_text_format, .. }: &'a SnippetTextEdit, + text: &'b mut Rope, ) -> rootcause::Result<()> { match insert_text_format { Some(lsp_types::InsertTextFormat::SNIPPET) => { @@ -504,9 +515,9 @@ impl TextArea { } Ok(()) } - pub fn apply_snippet_tedit( - &mut self, - SnippetTextEdit { range,new_text, insert_text_format, .. }: &SnippetTextEdit, + pub fn apply_snippet_tedit<'a, 'b>( + &'a mut self, + SnippetTextEdit { range,new_text, insert_text_format, .. }: &'b SnippetTextEdit, ) -> rootcause::Result<()> { match insert_text_format { Some(lsp_types::InsertTextFormat::SNIPPET) => self |