1use crate::block::{BlockError, BlockRange};
55use crate::diff::{apply, diff_at, ApplyError, Change};
56use crate::node::{Mark, Node};
57use crate::range::{Position, Range};
58use serde_json::{Map, Value};
59
60pub struct Transform<'a> {
67 root: &'a mut Node,
68 changes: Vec<Change>,
69 undo: Vec<Change>,
71}
72
73impl Node {
74 pub fn transform(&mut self) -> Transform<'_> {
76 Transform {
77 root: self,
78 changes: Vec::new(),
79 undo: Vec::new(),
80 }
81 }
82
83 pub fn apply_inverting(&mut self, changes: Vec<Change>) -> Result<Vec<Change>, ApplyError> {
102 let mut undo = Vec::with_capacity(changes.len());
103 for change in changes {
104 match apply_inverting_one(self, change) {
105 Ok(inv) => undo.extend(inv),
106 Err(e) => {
107 rollback(self, undo);
108 return Err(e);
109 }
110 }
111 }
112 undo.reverse();
113 Ok(undo)
114 }
115}
116
117fn rollback(root: &mut Node, undo: Vec<Change>) {
119 for change in undo.into_iter().rev() {
120 let _ = apply_inverting_one(root, change);
122 }
123}
124
125fn at_mut<'n>(root: &'n mut Node, path: &[usize]) -> Result<&'n mut Node, ApplyError> {
126 root.node_at_mut(path).ok_or_else(|| ApplyError {
127 path: path.to_vec(),
128 })
129}
130
131fn child_err(path: &[usize], index: usize) -> ApplyError {
132 let mut p = path.to_vec();
133 p.push(index);
134 ApplyError { path: p }
135}
136
137fn apply_inverting_one(root: &mut Node, change: Change) -> Result<Option<Change>, ApplyError> {
146 let empty_attrs = |n: &Node| matches!(&n.attrs, Some(a) if a.is_empty());
147 Ok(match change {
148 Change::SetAttr { path, key, value } => {
149 let node = at_mut(root, &path)?;
150 if empty_attrs(node) {
151 let before = node.clone();
152 node.set_attr(key, value);
153 Some(Change::Replace { path, node: before })
154 } else {
155 Some(match node.set_attr(key.clone(), value) {
156 Some(prev) => Change::SetAttr {
157 path,
158 key,
159 value: prev,
160 },
161 None => Change::RemoveAttr { path, key },
162 })
163 }
164 }
165 Change::RemoveAttr { path, key } => {
166 let node = at_mut(root, &path)?;
167 if empty_attrs(node) {
168 let before = node.clone();
170 node.remove_attr(&key);
171 Some(Change::Replace { path, node: before })
172 } else {
173 node.remove_attr(&key)
174 .map(|value| Change::SetAttr { path, key, value })
175 }
176 }
177 Change::SetText { path, text } => {
178 let node = at_mut(root, &path)?;
179 let prev = std::mem::replace(&mut node.text, text);
180 Some(Change::SetText { path, text: prev })
181 }
182 Change::SpliceText {
183 path,
184 from,
185 len_del,
186 insert,
187 } => {
188 let prev = at_mut(root, &path)?.text.clone();
189 let splice = Change::SpliceText {
190 path,
191 from,
192 len_del,
193 insert,
194 };
195 apply(root, std::slice::from_ref(&splice))?;
196 let Change::SpliceText { path, insert, .. } = splice else {
197 unreachable!()
198 };
199 match prev {
200 None if root.node_at(&path).is_some_and(|n| n.text.is_none()) => None,
202 None => Some(Change::SetText { path, text: None }),
203 Some(t) => Some(Change::SpliceText {
204 path,
205 from,
206 len_del: insert.chars().count(),
207 insert: t.chars().skip(from).take(len_del).collect(),
208 }),
209 }
210 }
211 Change::SetMarks { path, marks } => {
212 let node = at_mut(root, &path)?;
213 let prev = std::mem::replace(&mut node.marks, marks);
214 Some(Change::SetMarks { path, marks: prev })
215 }
216 Change::SetExtra { path, key, value } => {
217 let node = at_mut(root, &path)?;
218 Some(match node.extra.insert(key.clone(), value) {
219 Some(prev) => Change::SetExtra {
220 path,
221 key,
222 value: prev,
223 },
224 None => Change::RemoveExtra { path, key },
225 })
226 }
227 Change::RemoveExtra { path, key } => {
228 let node = at_mut(root, &path)?;
229 node.extra
230 .remove(&key)
231 .map(|value| Change::SetExtra { path, key, value })
232 }
233 Change::Insert { path, index, node } => {
234 let parent = at_mut(root, &path)?;
235 if index > parent.child_count() {
236 return Err(child_err(&path, index));
237 }
238 if matches!(&parent.content, Some(c) if c.is_empty()) {
239 let before = parent.clone();
242 parent.insert_child(index, node);
243 Some(Change::Replace { path, node: before })
244 } else {
245 parent.insert_child(index, node);
246 Some(Change::Remove { path, index })
247 }
248 }
249 Change::Remove { path, index } => {
250 let parent = at_mut(root, &path)?;
251 let node = parent
252 .remove_child(index)
253 .ok_or_else(|| child_err(&path, index))?;
254 Some(Change::Insert { path, index, node })
255 }
256 Change::Replace { path, node } => {
257 let old = match path.split_last() {
258 None => std::mem::replace(root, node),
259 Some((&last, parent)) => at_mut(root, parent)?
260 .replace_child(last, node)
261 .ok_or_else(|| ApplyError { path: path.clone() })?,
262 };
263 Some(Change::Replace { path, node: old })
264 }
265 Change::Move { path, from, to } => {
266 let mv = Change::Move { path, from, to };
267 apply(root, std::slice::from_ref(&mv))?;
268 let Change::Move { path, .. } = mv else {
269 unreachable!()
270 };
271 Some(Change::Move {
272 path,
273 from: to,
274 to: from,
275 })
276 }
277 })
278}
279
280impl<'a> Transform<'a> {
281 fn push(&mut self, change: Change) -> Result<&mut Self, ApplyError> {
283 let inv = apply_inverting_one(self.root, change.clone())?;
284 self.changes.push(change);
285 self.undo.extend(inv);
286 Ok(self)
287 }
288
289 pub fn set_attr(
291 &mut self,
292 path: Vec<usize>,
293 key: impl Into<String>,
294 value: impl Into<Value>,
295 ) -> Result<&mut Self, ApplyError> {
296 self.push(Change::SetAttr {
297 path,
298 key: key.into(),
299 value: value.into(),
300 })
301 }
302
303 pub fn remove_attr(
305 &mut self,
306 path: Vec<usize>,
307 key: impl Into<String>,
308 ) -> Result<&mut Self, ApplyError> {
309 self.push(Change::RemoveAttr {
310 path,
311 key: key.into(),
312 })
313 }
314
315 pub fn set_text(
317 &mut self,
318 path: Vec<usize>,
319 text: Option<String>,
320 ) -> Result<&mut Self, ApplyError> {
321 self.push(Change::SetText { path, text })
322 }
323
324 pub fn set_marks(
326 &mut self,
327 path: Vec<usize>,
328 marks: Option<Vec<Mark>>,
329 ) -> Result<&mut Self, ApplyError> {
330 self.push(Change::SetMarks { path, marks })
331 }
332
333 pub fn set_extra(
335 &mut self,
336 path: Vec<usize>,
337 key: impl Into<String>,
338 value: impl Into<Value>,
339 ) -> Result<&mut Self, ApplyError> {
340 self.push(Change::SetExtra {
341 path,
342 key: key.into(),
343 value: value.into(),
344 })
345 }
346
347 pub fn remove_extra(
349 &mut self,
350 path: Vec<usize>,
351 key: impl Into<String>,
352 ) -> Result<&mut Self, ApplyError> {
353 self.push(Change::RemoveExtra {
354 path,
355 key: key.into(),
356 })
357 }
358
359 pub fn insert(
361 &mut self,
362 path: Vec<usize>,
363 index: usize,
364 node: Node,
365 ) -> Result<&mut Self, ApplyError> {
366 self.push(Change::Insert { path, index, node })
367 }
368
369 pub fn remove(&mut self, path: Vec<usize>, index: usize) -> Result<&mut Self, ApplyError> {
371 self.push(Change::Remove { path, index })
372 }
373
374 pub fn replace(&mut self, path: Vec<usize>, node: Node) -> Result<&mut Self, ApplyError> {
376 self.push(Change::Replace { path, node })
377 }
378
379 pub fn move_child(
382 &mut self,
383 path: Vec<usize>,
384 from: usize,
385 to: usize,
386 ) -> Result<&mut Self, ApplyError> {
387 self.push(Change::Move { path, from, to })
388 }
389
390 pub fn apply_change(&mut self, change: Change) -> Result<&mut Self, ApplyError> {
394 self.push(change)
395 }
396
397 pub fn changes(&self) -> &[Change] {
399 &self.changes
400 }
401
402 pub fn finish(self) -> Vec<Change> {
404 self.changes
405 }
406
407 pub fn inverse(&self) -> Vec<Change> {
411 self.undo.iter().rev().cloned().collect()
412 }
413
414 pub fn finish_with_inverse(self) -> (Vec<Change>, Vec<Change>) {
417 let mut undo = self.undo;
418 undo.reverse();
419 (self.changes, undo)
420 }
421
422 pub fn rollback(self) {
425 rollback(self.root, self.undo);
426 }
427}
428
429impl Transform<'_> {
437 fn record_structural<F>(&mut self, scope: &[usize], f: F) -> Result<&mut Self, BlockError>
441 where
442 F: FnOnce(&mut Node) -> Result<(), BlockError>,
443 {
444 let scope = if self.root.node_at(scope).is_some() {
447 scope
448 } else {
449 &[]
450 };
451 let before = self.root.node_at(scope).cloned().unwrap_or_default();
452 if let Err(e) = f(self.root) {
453 if let Some(n) = self.root.node_at_mut(scope) {
454 *n = before;
455 }
456 return Err(e);
457 }
458 let after = self
459 .root
460 .node_at(scope)
461 .ok_or_else(|| BlockError::PathNotFound {
462 path: scope.to_vec(),
463 })?;
464 let patch = diff_at(&before, after, scope);
465 if !patch.is_empty() {
466 self.changes.extend(patch);
467 self.undo.push(Change::Replace {
468 path: scope.to_vec(),
469 node: before,
470 });
471 }
472 Ok(self)
473 }
474
475 pub fn set_block_type(
477 &mut self,
478 path: Vec<usize>,
479 new_type: impl Into<String>,
480 attrs: Option<Map<String, Value>>,
481 ) -> Result<&mut Self, BlockError> {
482 self.record_structural(&path.clone(), |root| {
483 root.set_block_type(&path, new_type, attrs)
484 })
485 }
486
487 pub fn split_block(
489 &mut self,
490 path: Vec<usize>,
491 at: usize,
492 depth: usize,
493 ) -> Result<&mut Self, BlockError> {
494 let scope = split_scope(&path, depth).to_vec();
495 self.record_structural(&scope, |root| root.split_block(&path, at, depth))
496 }
497
498 pub fn split_block_at(
500 &mut self,
501 path: Vec<usize>,
502 pos: Position,
503 depth: usize,
504 ) -> Result<&mut Self, BlockError> {
505 let scope = split_scope(&path, depth).to_vec();
506 self.record_structural(&scope, |root| root.split_block_at(&path, pos, depth))
507 }
508
509 pub fn join_blocks(
511 &mut self,
512 parent: Vec<usize>,
513 index: usize,
514 ) -> Result<&mut Self, BlockError> {
515 self.record_structural(&parent.clone(), |root| root.join_blocks(&parent, index))
516 }
517
518 pub fn wrap(
520 &mut self,
521 path: Vec<usize>,
522 wrapper_type: impl Into<String>,
523 attrs: Option<Map<String, Value>>,
524 ) -> Result<&mut Self, BlockError> {
525 self.record_structural(&path.clone(), |root| root.wrap(&path, wrapper_type, attrs))
527 }
528
529 pub fn wrap_range(
531 &mut self,
532 range: BlockRange,
533 wrapper_type: impl Into<String>,
534 attrs: Option<Map<String, Value>>,
535 ) -> Result<&mut Self, BlockError> {
536 self.record_structural(&range.parent.clone(), |root| {
537 root.wrap_range(&range, wrapper_type, attrs)
538 })
539 }
540
541 pub fn lift(&mut self, path: Vec<usize>) -> Result<&mut Self, BlockError> {
543 let scope = path[..path.len().saturating_sub(2)].to_vec();
545 self.record_structural(&scope, |root| root.lift(&path))
546 }
547}
548
549fn split_scope(path: &[usize], depth: usize) -> &[usize] {
552 let k = depth.min(path.len().saturating_sub(1));
553 &path[..path.len().saturating_sub(1 + k)]
554}
555
556impl Transform<'_> {
561 fn at_block<F>(&mut self, block_path: Vec<usize>, f: F) -> Result<&mut Self, BlockError>
562 where
563 F: FnOnce(&mut Node) -> Result<(), BlockError>,
564 {
565 self.record_structural(&block_path.clone(), move |root| {
566 let block = root
567 .node_at_mut(&block_path)
568 .ok_or_else(|| BlockError::PathNotFound {
569 path: block_path.clone(),
570 })?;
571 f(block)
572 })
573 }
574
575 pub fn insert_text_at(
577 &mut self,
578 block_path: Vec<usize>,
579 pos: Position,
580 text: impl Into<String>,
581 marks: Option<Vec<Mark>>,
582 ) -> Result<&mut Self, BlockError> {
583 let text = text.into();
584 self.at_block(block_path, move |block| {
585 block.insert_text(pos, &text, marks.as_deref())?;
586 Ok(())
587 })
588 }
589
590 pub fn delete_range_in(
592 &mut self,
593 block_path: Vec<usize>,
594 range: Range,
595 ) -> Result<&mut Self, BlockError> {
596 self.at_block(block_path, move |block| {
597 block.delete_range(range)?;
598 Ok(())
599 })
600 }
601
602 pub fn replace_range_in(
604 &mut self,
605 block_path: Vec<usize>,
606 range: Range,
607 text: impl Into<String>,
608 marks: Option<Vec<Mark>>,
609 ) -> Result<&mut Self, BlockError> {
610 let text = text.into();
611 self.at_block(block_path, move |block| {
612 block.replace_range(range, &text, marks.as_deref())?;
613 Ok(())
614 })
615 }
616
617 pub fn add_mark_range_in(
619 &mut self,
620 block_path: Vec<usize>,
621 range: Range,
622 mark: Mark,
623 ) -> Result<&mut Self, BlockError> {
624 self.at_block(block_path, move |block| {
625 block.add_mark_range(range, mark)?;
626 Ok(())
627 })
628 }
629
630 pub fn remove_mark_range_in(
632 &mut self,
633 block_path: Vec<usize>,
634 range: Range,
635 mark_type: impl Into<String>,
636 ) -> Result<&mut Self, BlockError> {
637 let mark_type = mark_type.into();
638 self.at_block(block_path, move |block| {
639 block.remove_mark_range(range, &mark_type)?;
640 Ok(())
641 })
642 }
643}