Simplify changeset tracking.
This commit is contained in:
parent
518426b9f4
commit
490e23b645
3 changed files with 40 additions and 19 deletions
|
@ -25,7 +25,8 @@ pub struct State {
|
|||
|
||||
//
|
||||
pub syntax: Option<Syntax>,
|
||||
pub changes: Option<ChangeSet>,
|
||||
/// Pending changes since last history commit.
|
||||
pub changes: ChangeSet,
|
||||
pub old_state: Option<(Rope, Selection)>,
|
||||
}
|
||||
|
||||
|
@ -45,6 +46,8 @@ pub enum Granularity {
|
|||
impl State {
|
||||
#[must_use]
|
||||
pub fn new(doc: Rope) -> Self {
|
||||
let changes = ChangeSet::new(&doc);
|
||||
|
||||
Self {
|
||||
path: None,
|
||||
doc,
|
||||
|
@ -52,7 +55,7 @@ impl State {
|
|||
mode: Mode::Normal,
|
||||
restore_cursor: false,
|
||||
syntax: None,
|
||||
changes: None,
|
||||
changes,
|
||||
old_state: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -342,6 +342,22 @@ pub struct Transaction {
|
|||
// scroll_into_view
|
||||
}
|
||||
|
||||
/// Like std::mem::replace() except it allows the replacement value to be mapped from the
|
||||
/// original value.
|
||||
pub fn take_with<T, F>(mut_ref: &mut T, closure: F)
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
use std::{panic, ptr};
|
||||
|
||||
unsafe {
|
||||
let old_t = ptr::read(mut_ref);
|
||||
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| closure(old_t)))
|
||||
.unwrap_or_else(|_| ::std::process::abort());
|
||||
ptr::write(mut_ref, new_t);
|
||||
}
|
||||
}
|
||||
|
||||
impl Transaction {
|
||||
/// Create a new, empty transaction.
|
||||
pub fn new(state: &mut State) -> Self {
|
||||
|
@ -364,11 +380,9 @@ impl Transaction {
|
|||
}
|
||||
|
||||
// Compose this transaction with the previous one
|
||||
let old_changes = state.changes.take();
|
||||
state.changes = Some(old_changes.map_or_else(
|
||||
|| self.changes.clone(),
|
||||
|changes| changes.compose(self.changes.clone()).unwrap(),
|
||||
));
|
||||
take_with(&mut state.changes, |changes| {
|
||||
changes.compose(self.changes.clone()).unwrap()
|
||||
});
|
||||
|
||||
if let Some(syntax) = &mut state.syntax {
|
||||
// TODO: no unwrap
|
||||
|
|
|
@ -368,22 +368,26 @@ pub fn open_below(view: &mut View, _count: usize) {
|
|||
// O inserts a new line before each line with a selection
|
||||
|
||||
fn append_changes_to_history(view: &mut View) {
|
||||
if let Some(changes) = view.state.changes.take() {
|
||||
// Instead of doing this messy merge we could always commit, and based on transaction
|
||||
// annotations either add a new layer or compose into the previous one.
|
||||
let transaction = Transaction::from(changes).with_selection(view.state.selection().clone());
|
||||
let (doc, selection) = view.state.old_state.take().unwrap();
|
||||
let mut old_state = State::new(doc);
|
||||
old_state.selection = selection;
|
||||
|
||||
// TODO: take transaction by value?
|
||||
view.history.commit_revision(&transaction, &old_state);
|
||||
if view.state.changes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: need to start the state with these vals
|
||||
let new_changeset = ChangeSet::new(view.state.doc());
|
||||
let changes = std::mem::replace(&mut view.state.changes, new_changeset);
|
||||
// Instead of doing this messy merge we could always commit, and based on transaction
|
||||
// annotations either add a new layer or compose into the previous one.
|
||||
let transaction = Transaction::from(changes).with_selection(view.state.selection().clone());
|
||||
|
||||
// HAXX: we need to reconstruct the state as it was before the changes..
|
||||
let (doc, selection) = view.state.old_state.take().unwrap();
|
||||
let mut old_state = State::new(doc);
|
||||
old_state.selection = selection;
|
||||
|
||||
// TODO: take transaction by value?
|
||||
view.history.commit_revision(&transaction, &old_state);
|
||||
|
||||
// TODO: need to start the state with these vals
|
||||
// HAXX
|
||||
view.state.changes = Some(ChangeSet::new(view.state.doc()));
|
||||
view.state.old_state = Some((view.state.doc().clone(), view.state.selection.clone()));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue