A simple CPU rendered GUI IDE experience.
handle the weird wsedits
bendn 3 weeks ago
parent d1b7d49 · commit 150ff70
-rw-r--r--src/edi/input_handlers/keyboard.rs16
-rw-r--r--src/edi/wsedit.rs73
-rw-r--r--src/hov.rs3
-rw-r--r--src/text.rs23
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),
diff --git a/src/hov.rs b/src/hov.rs
index ac5debf..2770588 100644
--- a/src/hov.rs
+++ b/src/hov.rs
@@ -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