diff options
Diffstat (limited to 'helix-core/src')
-rw-r--r-- | helix-core/src/state.rs | 7 | ||||
-rw-r--r-- | helix-core/src/transaction.rs | 24 |
2 files changed, 24 insertions, 7 deletions
diff --git a/helix-core/src/state.rs b/helix-core/src/state.rs index d8aa3ed4..fde6a866 100644 --- a/helix-core/src/state.rs +++ b/helix-core/src/state.rs @@ -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, } } diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index dfb1bbe1..86fc0bc8 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -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 |