on master help sign in
Simplify changeset tracking.
490e23bBlaž Hrastnik
helix-core/src/state.rs+5−2
@@ -25,7 +25,8 @@ pub struct State {
25
25
26 //
26 //
27 pub syntax: Option<Syntax>,
27 pub syntax: Option<Syntax>,
28+ /// Pending changes since last history commit.
28− pub changes: Option<ChangeSet>,
29+ pub changes: ChangeSet,
29 pub old_state: Option<(Rope, Selection)>,
30 pub old_state: Option<(Rope, Selection)>,
30}
31}
31
32
@@ -45,6 +46,8 @@ pub enum Granularity {
45impl State {
46impl State {
46 #[must_use]
47 #[must_use]
47 pub fn new(doc: Rope) -> Self {
48 pub fn new(doc: Rope) -> Self {
49+ let changes = ChangeSet::new(&doc);
50+
48 Self {
51 Self {
49 path: None,
52 path: None,
50 doc,
53 doc,
@@ -52,7 +55,7 @@ impl State {
52 mode: Mode::Normal,
55 mode: Mode::Normal,
53 restore_cursor: false,
56 restore_cursor: false,
54 syntax: None,
57 syntax: None,
55− changes: None,
58+ changes,
56 old_state: None,
59 old_state: None,
57 }
60 }
58 }
61 }
helix-core/src/transaction.rs+19−5
@@ -342,6 +342,22 @@ pub struct Transaction {
342 // scroll_into_view
342 // scroll_into_view
343}
343}
344
344
345+/// Like std::mem::replace() except it allows the replacement value to be mapped from the
346+/// original value.
347+pub fn take_with<T, F>(mut_ref: &mut T, closure: F)
348+where
349+ F: FnOnce(T) -> T,
350+{
351+ use std::{panic, ptr};
352+
353+ unsafe {
354+ let old_t = ptr::read(mut_ref);
355+ let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| closure(old_t)))
356+ .unwrap_or_else(|_| ::std::process::abort());
357+ ptr::write(mut_ref, new_t);
358+ }
359+}
360+
345impl Transaction {
361impl Transaction {
346 /// Create a new, empty transaction.
362 /// Create a new, empty transaction.
347 pub fn new(state: &mut State) -> Self {
363 pub fn new(state: &mut State) -> Self {
@@ -364,11 +380,9 @@ impl Transaction {
364 }
380 }
365
381
366 // Compose this transaction with the previous one
382 // Compose this transaction with the previous one
367− let old_changes = state.changes.take();
383+ take_with(&mut state.changes, |changes| {
368− state.changes = Some(old_changes.map_or_else(
369− || self.changes.clone(),
370− |changes| changes.compose(self.changes.clone()).unwrap(),
384+ changes.compose(self.changes.clone()).unwrap()
371− ));
385+ });
372
386
373 if let Some(syntax) = &mut state.syntax {
387 if let Some(syntax) = &mut state.syntax {
374 // TODO: no unwrap
388 // TODO: no unwrap
helix-view/src/commands.rs+16−12
@@ -368,22 +368,26 @@ pub fn open_below(view: &mut View, _count: usize) {
368// O inserts a new line before each line with a selection
368// O inserts a new line before each line with a selection
369
369
370fn append_changes_to_history(view: &mut View) {
370fn append_changes_to_history(view: &mut View) {
371− if let Some(changes) = view.state.changes.take() {
371+ if view.state.changes.is_empty() {
372− // Instead of doing this messy merge we could always commit, and based on transaction
372+ return;
373− // annotations either add a new layer or compose into the previous one.
374− let transaction = Transaction::from(changes).with_selection(view.state.selection().clone());
375− let (doc, selection) = view.state.old_state.take().unwrap();
376− let mut old_state = State::new(doc);
377− old_state.selection = selection;
378−
379− // TODO: take transaction by value?
380− view.history.commit_revision(&transaction, &old_state);
381 }
373 }
382
374
383− // TODO: need to start the state with these vals
375+ let new_changeset = ChangeSet::new(view.state.doc());
376+ let changes = std::mem::replace(&mut view.state.changes, new_changeset);
377+ // Instead of doing this messy merge we could always commit, and based on transaction
378+ // annotations either add a new layer or compose into the previous one.
379+ let transaction = Transaction::from(changes).with_selection(view.state.selection().clone());
380+
381+ // HAXX: we need to reconstruct the state as it was before the changes..
382+ let (doc, selection) = view.state.old_state.take().unwrap();
383+ let mut old_state = State::new(doc);
384+ old_state.selection = selection;
384
385
386+ // TODO: take transaction by value?
387+ view.history.commit_revision(&transaction, &old_state);
388+
389+ // TODO: need to start the state with these vals
385 // HAXX
390 // HAXX
386− view.state.changes = Some(ChangeSet::new(view.state.doc()));
387 view.state.old_state = Some((view.state.doc().clone(), view.state.selection.clone()));
391 view.state.old_state = Some((view.state.doc().clone(), view.state.selection.clone()));
388}
392}
389
393