@@ -1,4 +1,5 @@
1use crate::{Range, Rope, Selection, State, Tendril};
1use crate::{Range, Rope, Selection, State, Tendril};
2use std::convert::TryFrom;
3use std::convert::TryFrom;
4/// (from, to, replacement)
5/// (from, to, replacement)
@@ -21,7 +22,7 @@ pub enum Assoc {
23// ChangeSpec = Change | ChangeSet | Vec<Change>
24// ChangeSpec = Change | ChangeSet | Vec<Change>
24−#[derive(Debug)]
25+#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct ChangeSet {
26pub struct ChangeSet {
26 pub(crate) changes: Vec<Operation>,
27 pub(crate) changes: Vec<Operation>,
27 /// The required document length. Will refuse to apply changes unless it matches.
28 /// The required document length. Will refuse to apply changes unless it matches.
@@ -185,8 +186,38 @@ impl ChangeSet {
187 /// Returns a new changeset that reverts this one. Useful for `undo` implementation.
188 /// Returns a new changeset that reverts this one. Useful for `undo` implementation.
189+ /// The document parameter expects the original document before this change was applied.
188− pub fn invert(self) -> Self {
190+ pub fn invert(&self, original_doc: &Rope) -> Self {
189− unimplemented!()
191+ if original_doc.len_chars() != self.len {
192+ panic!("Document length mismatch");
196+ let mut changes = Vec::with_capacity(self.changes.len());
200+ for change in &self.changes {
204+ changes.push(Retain(*n));
209+ let text = Cow::from(original_doc.slice(pos..pos + *n));
210+ changes.push(Insert(Tendril::from_slice(&text)));
214+ changes.push(Delete(s.len()));
220+ Self { changes, len }
192 /// Returns true if applied successfully.
223 /// Returns true if applied successfully.
@@ -306,6 +337,7 @@ impl ChangeSet {
307/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
338/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
308/// a single transaction.
339/// a single transaction.
309pub struct Transaction {
341pub struct Transaction {
310 /// Changes made to the buffer.
342 /// Changes made to the buffer.
311 pub(crate) changes: ChangeSet,
343 pub(crate) changes: ChangeSet,
@@ -352,6 +384,18 @@ impl Transaction {
387+ /// Generate a transaction that reverts this one.
388+ pub fn invert(&self, original: &State) -> Self {
389+ let changes = self.changes.invert(original.doc());
390+ // Store the current cursor position
391+ let selection = original.selection.clone();
395+ selection: Some(selection),
355 pub fn with_selection(mut self, selection: Selection) -> Self {
399 pub fn with_selection(mut self, selection: Selection) -> Self {
356 self.selection = Some(selection);
400 self.selection = Some(selection);
@@ -444,6 +488,33 @@ mod test {
444 // TODO: assert
488 // TODO: assert
495+ let changes = ChangeSet {
496+ changes: vec![Retain(4), Delete(5), Insert("test".into()), Retain(3)],
500+ let doc = Rope::from("123 hello xz");
501+ let revert = changes.invert(&doc);
503+ let mut doc2 = doc.clone();
504+ changes.apply(&mut doc2);
506+ // a revert is different
507+ assert_ne!(changes, revert);
508+ assert_ne!(doc, doc2);
510+ // but inverting a revert will give us the original
511+ assert_eq!(changes, revert.invert(&doc2));
513+ // applying a revert gives us back the original
514+ revert.apply(&mut doc2);
515+ assert_eq!(doc, doc2);
448 fn map_pos() {
519 fn map_pos() {
449 use Operation::*;
520 use Operation::*;