Merge pull request #62 from pickfire/cell

Separate document history into Cell
imgbot
Corey Powell 3 years ago committed by GitHub
commit 7761c88d61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -65,9 +65,7 @@ impl History {
self.cursor == 0 self.cursor == 0
} }
// TODO: I'd like to pass Transaction by reference but it fights with the borrowck pub fn undo(&mut self) -> Option<&Transaction> {
pub fn undo(&mut self) -> Option<Transaction> {
if self.at_root() { if self.at_root() {
// We're at the root of undo, nothing to do. // We're at the root of undo, nothing to do.
return None; return None;
@ -77,17 +75,17 @@ impl History {
self.cursor = current_revision.parent; self.cursor = current_revision.parent;
Some(current_revision.revert.clone()) Some(&current_revision.revert)
} }
pub fn redo(&mut self) -> Option<Transaction> { pub fn redo(&mut self) -> Option<&Transaction> {
let current_revision = &self.revisions[self.cursor]; let current_revision = &self.revisions[self.cursor];
// for now, simply pick the latest child (linear undo / redo) // for now, simply pick the latest child (linear undo / redo)
if let Some((index, transaction)) = current_revision.children.last() { if let Some((index, transaction)) = current_revision.children.last() {
self.cursor = *index; self.cursor = *index;
return Some(transaction.clone()); return Some(&transaction);
} }
None None
} }

@ -415,7 +415,7 @@ impl ChangeSet {
/// Transaction represents a single undoable unit of changes. Several changes can be grouped into /// Transaction represents a single undoable unit of changes. Several changes can be grouped into
/// a single transaction. /// a single transaction.
#[derive(Debug, Clone)] #[derive(Debug, Default, Clone)]
pub struct Transaction { pub struct Transaction {
changes: ChangeSet, changes: ChangeSet,
selection: Option<Selection>, selection: Option<Selection>,

@ -1,4 +1,5 @@
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use std::cell::Cell;
use std::future::Future; use std::future::Future;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
@ -40,7 +41,10 @@ pub struct Document {
/// State at last commit. Used for calculating reverts. /// State at last commit. Used for calculating reverts.
old_state: Option<State>, old_state: Option<State>,
/// Undo tree. /// Undo tree.
history: History, // It can be used as a cell where we will take it out to get some parts of the history and put
// it back as it separated from the edits. We could split out the parts manually but that will
// be more troublesome.
history: Cell<History>,
last_saved_revision: usize, last_saved_revision: usize,
version: i32, // should be usize? version: i32, // should be usize?
@ -121,7 +125,7 @@ impl Document {
old_state, old_state,
diagnostics: Vec::new(), diagnostics: Vec::new(),
version: 0, version: 0,
history: History::default(), history: Cell::new(History::default()),
last_saved_revision: 0, last_saved_revision: 0,
language_server: None, language_server: None,
} }
@ -190,7 +194,9 @@ impl Document {
let language_server = self.language_server.clone(); let language_server = self.language_server.clone();
// reset the modified flag // reset the modified flag
self.last_saved_revision = self.history.current_revision(); let history = self.history.take();
self.last_saved_revision = history.current_revision();
self.history.set(history);
async move { async move {
use tokio::{fs::File, io::AsyncWriteExt}; use tokio::{fs::File, io::AsyncWriteExt};
@ -335,7 +341,8 @@ impl Document {
} }
pub fn undo(&mut self, view_id: ViewId) -> bool { pub fn undo(&mut self, view_id: ViewId) -> bool {
if let Some(transaction) = self.history.undo() { let mut history = self.history.take();
if let Some(transaction) = history.undo() {
let success = self._apply(&transaction, view_id); let success = self._apply(&transaction, view_id);
// reset changeset to fix len // reset changeset to fix len
@ -343,11 +350,13 @@ impl Document {
return success; return success;
} }
self.history.set(history);
false false
} }
pub fn redo(&mut self, view_id: ViewId) -> bool { pub fn redo(&mut self, view_id: ViewId) -> bool {
if let Some(transaction) = self.history.redo() { let mut history = self.history.take();
if let Some(transaction) = history.redo() {
let success = self._apply(&transaction, view_id); let success = self._apply(&transaction, view_id);
// reset changeset to fix len // reset changeset to fix len
@ -355,6 +364,7 @@ impl Document {
return success; return success;
} }
self.history.set(history);
false false
} }
@ -373,7 +383,9 @@ impl Document {
// HAXX: we need to reconstruct the state as it was before the changes.. // HAXX: we need to reconstruct the state as it was before the changes..
let old_state = self.old_state.take().expect("no old_state available"); let old_state = self.old_state.take().expect("no old_state available");
self.history.commit_revision(&transaction, &old_state); let mut history = self.history.take();
history.commit_revision(&transaction, &old_state);
self.history.set(history);
} }
#[inline] #[inline]
@ -383,9 +395,11 @@ impl Document {
#[inline] #[inline]
pub fn is_modified(&self) -> bool { pub fn is_modified(&self) -> bool {
let history = self.history.take();
let current_revision = history.current_revision();
self.history.set(history);
self.path.is_some() self.path.is_some()
&& (self.history.current_revision() != self.last_saved_revision && (current_revision != self.last_saved_revision || !self.changes.is_empty())
|| !self.changes.is_empty())
} }
#[inline] #[inline]

Loading…
Cancel
Save