@@ -1,16 +1,16 @@
1use crate::{ChangeSet, Rope, State, Transaction};
1use crate::{ChangeSet, Rope, State, Transaction};
2+use smallvec::{smallvec, SmallVec};
3/// Undo-tree style history store.
4/// Undo-tree style history store.
4pub struct History {
5pub struct History {
5 revisions: Vec<Revision>,
6 revisions: Vec<Revision>,
6 cursor: usize,
7 cursor: usize,
10#[derive(Debug)]
10#[derive(Debug)]
11struct Revision {
11struct Revision {
13 parent: usize,
12 parent: usize,
13+ children: SmallVec<[(usize, Transaction); 1]>,
14 /// The transaction to revert to previous state.
14 /// The transaction to revert to previous state.
15 revert: Transaction,
15 revert: Transaction,
16 // selection before, selection after?
16 // selection before, selection after?
@@ -22,6 +22,7 @@ impl Default for History {
23 revisions: vec![Revision {
23 revisions: vec![Revision {
24 parent: 0,
24 parent: 0,
25+ children: SmallVec::new(),
25 revert: Transaction::from(ChangeSet::new(&Rope::new())),
26 revert: Transaction::from(ChangeSet::new(&Rope::new())),
27 cursor: 0,
28 cursor: 0,
@@ -31,18 +32,24 @@ impl Default for History {
32impl History {
33impl History {
33 pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
34 pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
34− // TODO: store both directions
35− // TODO: could store a single set if deletes also stored the text they delete
35+ // TODO: could store a single transaction, if deletes also stored the text they delete
36 let revert = transaction.invert(original);
36 let revert = transaction.invert(original);
38 let new_cursor = self.revisions.len();
38 let new_cursor = self.revisions.len();
39 self.revisions.push(Revision {
39 self.revisions.push(Revision {
40 parent: self.cursor,
40 parent: self.cursor,
41+ children: SmallVec::new(),
43− self.cursor = new_cursor;
45− // TODO: child tracking too?
45+ // add a reference to the parent
47+ .get_mut(self.cursor)
48+ .unwrap() // TODO: get_unchecked_mut
50+ .push((new_cursor, transaction.clone()));
52+ self.cursor = new_cursor;
@@ -57,9 +64,8 @@ impl History {
59 let current_revision = &self.revisions[self.cursor];
66 let current_revision = &self.revisions[self.cursor];
60− // unimplemented!("{:?}", revision);
67+
61− // unimplemented!("{:?}", state.doc().len_chars());
62− // TODO: pass the return value through?
68+ // TODO: pass the return value through? It should always succeed
63 let success = current_revision.revert.apply(state);
69 let success = current_revision.revert.apply(state);
65 if !success {
71 if !success {
@@ -72,13 +78,16 @@ impl History {
72 pub fn redo(&mut self, state: &mut State) {
78 pub fn redo(&mut self, state: &mut State) {
73 let current_revision = &self.revisions[self.cursor];
79 let current_revision = &self.revisions[self.cursor];
75− // TODO: pick the latest child
81+ // for now, simply pick the latest child (linear undo / redo)
82+ if let Some((index, transaction)) = current_revision.children.last() {
83+ let success = transaction.apply(state);
77− // if !success {
85+ if !success {
78− // panic!("Failed to apply undo!");
86+ panic!("Failed to apply redo!");
81− unimplemented!()
89+ self.cursor = *index;