aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2020-10-05 07:12:36 +0000
committerBlaž Hrastnik2020-10-13 14:13:56 +0000
commit04b15466347f3ae25125be081a159511ccbae670 (patch)
tree5aef6fb83f58ca1e779ef095eb14c5113e16dc99
parent8c7bc71ede213522efbcbb1b0fe91c0d47d2b47d (diff)
history.redo()
-rw-r--r--helix-core/src/history.rs37
1 files changed, 23 insertions, 14 deletions
diff --git a/helix-core/src/history.rs b/helix-core/src/history.rs
index 8d7164db..e6d9a738 100644
--- a/helix-core/src/history.rs
+++ b/helix-core/src/history.rs
@@ -1,16 +1,16 @@
use crate::{ChangeSet, Rope, State, Transaction};
+use smallvec::{smallvec, SmallVec};
/// Undo-tree style history store.
pub struct History {
revisions: Vec<Revision>,
cursor: usize,
- //
}
#[derive(Debug)]
struct Revision {
- // prev: usize,
parent: usize,
+ children: SmallVec<[(usize, Transaction); 1]>,
/// The transaction to revert to previous state.
revert: Transaction,
// selection before, selection after?
@@ -22,6 +22,7 @@ impl Default for History {
Self {
revisions: vec![Revision {
parent: 0,
+ children: SmallVec::new(),
revert: Transaction::from(ChangeSet::new(&Rope::new())),
}],
cursor: 0,
@@ -31,18 +32,24 @@ impl Default for History {
impl History {
pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
- // TODO: store both directions
- // TODO: could store a single set if deletes also stored the text they delete
+ // TODO: could store a single transaction, if deletes also stored the text they delete
let revert = transaction.invert(original);
let new_cursor = self.revisions.len();
self.revisions.push(Revision {
parent: self.cursor,
+ children: SmallVec::new(),
revert,
});
- self.cursor = new_cursor;
- // TODO: child tracking too?
+ // add a reference to the parent
+ self.revisions
+ .get_mut(self.cursor)
+ .unwrap() // TODO: get_unchecked_mut
+ .children
+ .push((new_cursor, transaction.clone()));
+
+ self.cursor = new_cursor;
}
#[inline]
@@ -57,9 +64,8 @@ impl History {
}
let current_revision = &self.revisions[self.cursor];
- // unimplemented!("{:?}", revision);
- // unimplemented!("{:?}", state.doc().len_chars());
- // TODO: pass the return value through?
+
+ // TODO: pass the return value through? It should always succeed
let success = current_revision.revert.apply(state);
if !success {
@@ -72,13 +78,16 @@ impl History {
pub fn redo(&mut self, state: &mut State) {
let current_revision = &self.revisions[self.cursor];
- // TODO: pick the latest child
+ // for now, simply pick the latest child (linear undo / redo)
+ if let Some((index, transaction)) = current_revision.children.last() {
+ let success = transaction.apply(state);
- // if !success {
- // panic!("Failed to apply undo!");
- // }
+ if !success {
+ panic!("Failed to apply redo!");
+ }
- unimplemented!()
+ self.cursor = *index;
+ }
}
}