on master help sign in
Follow parent links when calculating changes since a revision

The 'revisions' field on History can't be treated as linear: each Revision in the revisions Vec has a parent link and an optional child link. We can follow those to unroll the recent history.

commita3f321a531554b51160f3fe7e6da1c269030f3b6 authorMichael Davis <mcarsondavis@gmail.com> dateWed 23 Nov 2022, 13:02 (4 years ago) parent4a103db
2 files changed+24−10
helix-core/src/history.rs+21−10 helix-term/tests/test/commands.rs+3
helix-core/src/history.rs+21−10
@@ -126,16 +126,27 @@ impl History {
126126
127127 match revision.cmp(&self.current) {
128128 Equal => None,
129− Greater => self.revisions[self.current + 1..=revision]
130− .iter()
131− .map(|revision| &revision.inversion)
132− .cloned()
133− .reduce(|acc, inversion| acc.compose(inversion)),
134− Less => self.revisions[revision + 1..=self.current]
135− .iter()
136− .map(|revision| &revision.transaction)
137− .cloned()
138− .reduce(|acc, transaction| acc.compose(transaction)),
129+ Less => {
130+ let mut child = self.revisions[revision].last_child?.get();
131+ let mut transaction = self.revisions[child].transaction.clone();
132+ while child != self.current {
133+ child = self.revisions[child].last_child?.get();
134+ transaction = transaction.compose(self.revisions[child].transaction.clone());
135+ }
136+ Some(transaction)
137+ }
138+ Greater => {
139+ let mut inversion = self.revisions[revision].inversion.clone();
140+ let mut parent = self.revisions[revision].parent;
141+ while parent != self.current {
142+ parent = self.revisions[parent].parent;
143+ if parent == 0 {
144+ return None;
145+ }
146+ inversion = inversion.compose(self.revisions[parent].inversion.clone());
147+ }
148+ Some(inversion)
149+ }
139150 }
140151 }
141152
helix-term/tests/test/commands.rs+3
@@ -306,5 +306,8 @@ async fn test_undo_redo() -> anyhow::Result<()> {
306306 // * <C-i> Jump forward to line 1.
307307 test(("#[|]#", "[<space><C-s>kduU<C-o><C-i>", "#[|]#")).await?;
308308
309+ // In this case we 'redo' manually to ensure that the transactions are composing correctly.
310+ test(("#[|]#", "[<space>u[<space>u", "#[|]#")).await?;
311+
309312 Ok(())
310313}