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_mut().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.remove_extra(&key)
230 .map(|value| Change::SetExtra { path, key, value })
231 }
232 Change::Insert { path, index, node } => {
233 let parent = at_mut(root, &path)?;
234 if index > parent.child_count() {
235 return Err(child_err(&path, index));
236 }
237 if matches!(&parent.content, Some(c) if c.is_empty()) {
238 let before = parent.clone();
241 parent.insert_child(index, node);
242 Some(Change::Replace { path, node: before })
243 } else {
244 parent.insert_child(index, node);
245 Some(Change::Remove { path, index })
246 }
247 }
248 Change::Remove { path, index } => {
249 let parent = at_mut(root, &path)?;
250 let node = parent
251 .remove_child(index)
252 .ok_or_else(|| child_err(&path, index))?;
253 Some(Change::Insert { path, index, node })
254 }
255 Change::Replace { path, node } => {
256 let old = match path.split_last() {
257 None => std::mem::replace(root, node),
258 Some((&last, parent)) => at_mut(root, parent)?
259 .replace_child(last, node)
260 .ok_or_else(|| ApplyError { path: path.clone() })?,
261 };
262 Some(Change::Replace { path, node: old })
263 }
264 Change::Move { path, from, to } => {
265 let mv = Change::Move { path, from, to };
266 apply(root, std::slice::from_ref(&mv))?;
267 let Change::Move { path, .. } = mv else {
268 unreachable!()
269 };
270 Some(Change::Move {
271 path,
272 from: to,
273 to: from,
274 })
275 }
276 })
277}
278
279impl<'a> Transform<'a> {
280 fn push(&mut self, change: Change) -> Result<&mut Self, ApplyError> {
282 let inv = apply_inverting_one(self.root, change.clone())?;
283 self.changes.push(change);
284 self.undo.extend(inv);
285 Ok(self)
286 }
287
288 pub fn set_attr(
290 &mut self,
291 path: Vec<usize>,
292 key: impl Into<String>,
293 value: impl Into<Value>,
294 ) -> Result<&mut Self, ApplyError> {
295 self.push(Change::SetAttr {
296 path,
297 key: key.into(),
298 value: value.into(),
299 })
300 }
301
302 pub fn remove_attr(
304 &mut self,
305 path: Vec<usize>,
306 key: impl Into<String>,
307 ) -> Result<&mut Self, ApplyError> {
308 self.push(Change::RemoveAttr {
309 path,
310 key: key.into(),
311 })
312 }
313
314 pub fn set_text(
316 &mut self,
317 path: Vec<usize>,
318 text: Option<String>,
319 ) -> Result<&mut Self, ApplyError> {
320 self.push(Change::SetText { path, text })
321 }
322
323 pub fn set_marks(
325 &mut self,
326 path: Vec<usize>,
327 marks: Option<Vec<Mark>>,
328 ) -> Result<&mut Self, ApplyError> {
329 self.push(Change::SetMarks { path, marks })
330 }
331
332 pub fn set_extra(
334 &mut self,
335 path: Vec<usize>,
336 key: impl Into<String>,
337 value: impl Into<Value>,
338 ) -> Result<&mut Self, ApplyError> {
339 self.push(Change::SetExtra {
340 path,
341 key: key.into(),
342 value: value.into(),
343 })
344 }
345
346 pub fn remove_extra(
348 &mut self,
349 path: Vec<usize>,
350 key: impl Into<String>,
351 ) -> Result<&mut Self, ApplyError> {
352 self.push(Change::RemoveExtra {
353 path,
354 key: key.into(),
355 })
356 }
357
358 pub fn insert(
360 &mut self,
361 path: Vec<usize>,
362 index: usize,
363 node: Node,
364 ) -> Result<&mut Self, ApplyError> {
365 self.push(Change::Insert { path, index, node })
366 }
367
368 pub fn remove(&mut self, path: Vec<usize>, index: usize) -> Result<&mut Self, ApplyError> {
370 self.push(Change::Remove { path, index })
371 }
372
373 pub fn replace(&mut self, path: Vec<usize>, node: Node) -> Result<&mut Self, ApplyError> {
375 self.push(Change::Replace { path, node })
376 }
377
378 pub fn move_child(
381 &mut self,
382 path: Vec<usize>,
383 from: usize,
384 to: usize,
385 ) -> Result<&mut Self, ApplyError> {
386 self.push(Change::Move { path, from, to })
387 }
388
389 pub fn apply_change(&mut self, change: Change) -> Result<&mut Self, ApplyError> {
393 self.push(change)
394 }
395
396 pub fn changes(&self) -> &[Change] {
398 &self.changes
399 }
400
401 pub fn finish(self) -> Vec<Change> {
403 self.changes
404 }
405
406 pub fn inverse(&self) -> Vec<Change> {
410 self.undo.iter().rev().cloned().collect()
411 }
412
413 pub fn finish_with_inverse(self) -> (Vec<Change>, Vec<Change>) {
416 let mut undo = self.undo;
417 undo.reverse();
418 (self.changes, undo)
419 }
420
421 pub fn rollback(self) {
424 rollback(self.root, self.undo);
425 }
426}
427
428impl Transform<'_> {
436 fn record_structural<F>(&mut self, scope: &[usize], f: F) -> Result<&mut Self, BlockError>
440 where
441 F: FnOnce(&mut Node) -> Result<(), BlockError>,
442 {
443 let scope = if self.root.node_at(scope).is_some() {
446 scope
447 } else {
448 &[]
449 };
450 let before = self.root.node_at(scope).cloned().unwrap_or_default();
451 if let Err(e) = f(self.root) {
452 if let Some(n) = self.root.node_at_mut(scope) {
453 *n = before;
454 }
455 return Err(e);
456 }
457 let after = self
458 .root
459 .node_at(scope)
460 .ok_or_else(|| BlockError::PathNotFound {
461 path: scope.to_vec(),
462 })?;
463 let patch = diff_at(&before, after, scope);
464 if !patch.is_empty() {
465 self.changes.extend(patch);
466 self.undo.push(Change::Replace {
467 path: scope.to_vec(),
468 node: before,
469 });
470 }
471 Ok(self)
472 }
473
474 pub fn set_block_type(
476 &mut self,
477 path: Vec<usize>,
478 new_type: impl Into<String>,
479 attrs: Option<Map<String, Value>>,
480 ) -> Result<&mut Self, BlockError> {
481 self.record_structural(&path.clone(), |root| {
482 root.set_block_type(&path, new_type, attrs)
483 })
484 }
485
486 pub fn split_block(
488 &mut self,
489 path: Vec<usize>,
490 at: usize,
491 depth: usize,
492 ) -> Result<&mut Self, BlockError> {
493 let scope = split_scope(&path, depth).to_vec();
494 self.record_structural(&scope, |root| root.split_block(&path, at, depth))
495 }
496
497 pub fn split_block_at(
499 &mut self,
500 path: Vec<usize>,
501 pos: Position,
502 depth: usize,
503 ) -> Result<&mut Self, BlockError> {
504 let scope = split_scope(&path, depth).to_vec();
505 self.record_structural(&scope, |root| root.split_block_at(&path, pos, depth))
506 }
507
508 pub fn join_blocks(
510 &mut self,
511 parent: Vec<usize>,
512 index: usize,
513 ) -> Result<&mut Self, BlockError> {
514 self.record_structural(&parent.clone(), |root| root.join_blocks(&parent, index))
515 }
516
517 pub fn wrap(
519 &mut self,
520 path: Vec<usize>,
521 wrapper_type: impl Into<String>,
522 attrs: Option<Map<String, Value>>,
523 ) -> Result<&mut Self, BlockError> {
524 self.record_structural(&path.clone(), |root| root.wrap(&path, wrapper_type, attrs))
526 }
527
528 pub fn wrap_range(
530 &mut self,
531 range: BlockRange,
532 wrapper_type: impl Into<String>,
533 attrs: Option<Map<String, Value>>,
534 ) -> Result<&mut Self, BlockError> {
535 self.record_structural(&range.parent.clone(), |root| {
536 root.wrap_range(&range, wrapper_type, attrs)
537 })
538 }
539
540 pub fn lift(&mut self, path: Vec<usize>) -> Result<&mut Self, BlockError> {
542 let scope = path[..path.len().saturating_sub(2)].to_vec();
544 self.record_structural(&scope, |root| root.lift(&path))
545 }
546}
547
548fn split_scope(path: &[usize], depth: usize) -> &[usize] {
551 let k = depth.min(path.len().saturating_sub(1));
552 &path[..path.len().saturating_sub(1 + k)]
553}
554
555impl Transform<'_> {
560 fn at_block<F>(&mut self, block_path: Vec<usize>, f: F) -> Result<&mut Self, BlockError>
561 where
562 F: FnOnce(&mut Node) -> Result<(), BlockError>,
563 {
564 self.record_structural(&block_path.clone(), move |root| {
565 let block = root
566 .node_at_mut(&block_path)
567 .ok_or_else(|| BlockError::PathNotFound {
568 path: block_path.clone(),
569 })?;
570 f(block)
571 })
572 }
573
574 pub fn insert_text_at(
576 &mut self,
577 block_path: Vec<usize>,
578 pos: Position,
579 text: impl Into<String>,
580 marks: Option<Vec<Mark>>,
581 ) -> Result<&mut Self, BlockError> {
582 let text = text.into();
583 self.at_block(block_path, move |block| {
584 block.insert_text(pos, &text, marks.as_deref())?;
585 Ok(())
586 })
587 }
588
589 pub fn delete_range_in(
591 &mut self,
592 block_path: Vec<usize>,
593 range: Range,
594 ) -> Result<&mut Self, BlockError> {
595 self.at_block(block_path, move |block| {
596 block.delete_range(range)?;
597 Ok(())
598 })
599 }
600
601 pub fn replace_range_in(
603 &mut self,
604 block_path: Vec<usize>,
605 range: Range,
606 text: impl Into<String>,
607 marks: Option<Vec<Mark>>,
608 ) -> Result<&mut Self, BlockError> {
609 let text = text.into();
610 self.at_block(block_path, move |block| {
611 block.replace_range(range, &text, marks.as_deref())?;
612 Ok(())
613 })
614 }
615
616 pub fn add_mark_range_in(
618 &mut self,
619 block_path: Vec<usize>,
620 range: Range,
621 mark: Mark,
622 ) -> Result<&mut Self, BlockError> {
623 self.at_block(block_path, move |block| {
624 block.add_mark_range(range, mark)?;
625 Ok(())
626 })
627 }
628
629 pub fn remove_mark_range_in(
631 &mut self,
632 block_path: Vec<usize>,
633 range: Range,
634 mark_type: impl Into<String>,
635 ) -> Result<&mut Self, BlockError> {
636 let mark_type = mark_type.into();
637 self.at_block(block_path, move |block| {
638 block.remove_mark_range(range, &mark_type)?;
639 Ok(())
640 })
641 }
642}