on master help sign in
Separate document history into Cell

As history is used separately from the rest of the edits, separating it can avoid needless borrowing and cloning. But one need to be aware later.

commitf5f46b1fed242f0b5a206753f7f977299fb2ff65 authorIvan Tham <pickfire@riseup.net> dateWed 2 Jun 2021, 23:47 (5 years ago) parent0a6672c
3 files changed+27−15
helix-core/src/history.rs+4−6 helix-core/src/transaction.rs+1−1 helix-view/src/document.rs+22−8
helix-core/src/history.rs+4−6
@@ -65,9 +65,7 @@ impl History {
6565 self.cursor == 0
6666 }
6767
68− // TODO: I'd like to pass Transaction by reference but it fights with the borrowck
69−
70− pub fn undo(&mut self) -> Option<Transaction> {
68+ pub fn undo(&mut self) -> Option<&Transaction> {
7169 if self.at_root() {
7270 // We're at the root of undo, nothing to do.
7371 return None;
@@ -77,17 +75,17 @@ impl History {
7775
7876 self.cursor = current_revision.parent;
7977
80− Some(current_revision.revert.clone())
78+ Some(&current_revision.revert)
8179 }
8280
83− pub fn redo(&mut self) -> Option<Transaction> {
81+ pub fn redo(&mut self) -> Option<&Transaction> {
8482 let current_revision = &self.revisions[self.cursor];
8583
8684 // for now, simply pick the latest child (linear undo / redo)
8785 if let Some((index, transaction)) = current_revision.children.last() {
8886 self.cursor = *index;
8987
90− return Some(transaction.clone());
88+ return Some(&transaction);
9189 }
9290 None
9391 }
helix-core/src/transaction.rs+1−1
@@ -415,7 +415,7 @@ impl ChangeSet {
415415
416416/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
417417/// a single transaction.
418−#[derive(Debug, Clone)]
418+#[derive(Debug, Default, Clone)]
419419pub struct Transaction {
420420 changes: ChangeSet,
421421 selection: Option<Selection>,
helix-view/src/document.rs+22−8
@@ -1,4 +1,5 @@
11use anyhow::{Context, Error};
2+use std::cell::Cell;
23use std::future::Future;
34use std::path::{Component, Path, PathBuf};
45use std::sync::Arc;
@@ -40,7 +41,10 @@ pub struct Document {
4041 /// State at last commit. Used for calculating reverts.
4142 old_state: Option<State>,
4243 /// Undo tree.
43− history: History,
44+ // It can be used as a cell where we will take it out to get some parts of the history and put
45+ // it back as it separated from the edits. We could split out the parts manually but that will
46+ // be more troublesome.
47+ history: Cell<History>,
4448 last_saved_revision: usize,
4549 version: i32, // should be usize?
4650
@@ -121,7 +125,7 @@ impl Document {
121125 old_state,
122126 diagnostics: Vec::new(),
123127 version: 0,
124− history: History::default(),
128+ history: Cell::new(History::default()),
125129 last_saved_revision: 0,
126130 language_server: None,
127131 }
@@ -190,7 +194,9 @@ impl Document {
190194 let language_server = self.language_server.clone();
191195
192196 // reset the modified flag
193− self.last_saved_revision = self.history.current_revision();
197+ let history = self.history.take();
198+ self.last_saved_revision = history.current_revision();
199+ self.history.set(history);
194200
195201 async move {
196202 use tokio::{fs::File, io::AsyncWriteExt};
@@ -335,7 +341,8 @@ impl Document {
335341 }
336342
337343 pub fn undo(&mut self, view_id: ViewId) -> bool {
338− if let Some(transaction) = self.history.undo() {
344+ let mut history = self.history.take();
345+ if let Some(transaction) = history.undo() {
339346 let success = self._apply(&transaction, view_id);
340347
341348 // reset changeset to fix len
@@ -343,11 +350,13 @@ impl Document {
343350
344351 return success;
345352 }
353+ self.history.set(history);
346354 false
347355 }
348356
349357 pub fn redo(&mut self, view_id: ViewId) -> bool {
350− if let Some(transaction) = self.history.redo() {
358+ let mut history = self.history.take();
359+ if let Some(transaction) = history.redo() {
351360 let success = self._apply(&transaction, view_id);
352361
353362 // reset changeset to fix len
@@ -355,6 +364,7 @@ impl Document {
355364
356365 return success;
357366 }
367+ self.history.set(history);
358368 false
359369 }
360370
@@ -373,7 +383,9 @@ impl Document {
373383 // HAXX: we need to reconstruct the state as it was before the changes..
374384 let old_state = self.old_state.take().expect("no old_state available");
375385
376− self.history.commit_revision(&transaction, &old_state);
386+ let mut history = self.history.take();
387+ history.commit_revision(&transaction, &old_state);
388+ self.history.set(history);
377389 }
378390
379391 #[inline]
@@ -383,9 +395,11 @@ impl Document {
383395
384396 #[inline]
385397 pub fn is_modified(&self) -> bool {
398+ let history = self.history.take();
399+ let current_revision = history.current_revision();
400+ self.history.set(history);
386401 self.path.is_some()
387− && (self.history.current_revision() != self.last_saved_revision
388− || !self.changes.is_empty())
402+ && (current_revision != self.last_saved_revision || !self.changes.is_empty())
389403 }
390404
391405 #[inline]