diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index eec947dff..25a1a7621 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -94,8 +94,14 @@ impl ChangeSet { head_b = b; } // insertion in B - (a, Some(change @ Insert(..))) => { - changes.push(change); + (a, Some(Insert(current))) => { + // merge onto previous insert if possible + // TODO: do these as operations on a changeset + if let Some(Insert(prev)) = changes.last_mut() { + prev.push_tendril(¤t); + } else { + changes.push(Insert(current)); + } head_a = a; head_b = changes_b.next(); } @@ -422,7 +428,9 @@ impl Transaction { let mut last = 0; for (from, to, tendril) in changes { // Retain from last "to" to current "from" - acc.push(Operation::Retain(from - last)); + if from - last > 0 { + acc.push(Operation::Retain(from - last)); + } let span = to - from; match tendril { Some(text) => { @@ -581,4 +589,36 @@ mod test { transaction.apply(&mut state); assert_eq!(state.doc, Rope::from_str("hello void! 123")); } + + #[test] + fn insert_composition() { + let mut state = State::new("".into()); + let t1 = Transaction::insert(&state, Tendril::from_char('h')); + t1.apply(&mut state); + let t2 = Transaction::insert(&state, Tendril::from_char('e')); + t2.apply(&mut state); + let t3 = Transaction::insert(&state, Tendril::from_char('l')); + t3.apply(&mut state); + let t4 = Transaction::insert(&state, Tendril::from_char('l')); + t4.apply(&mut state); + let t5 = Transaction::insert(&state, Tendril::from_char('o')); + t5.apply(&mut state); + + assert_eq!(state.doc, Rope::from_str("hello")); + + // changesets as follows: + // h + // retain 1, e + // retain 2, l + + let mut changes = t1 + .changes + .compose(t2.changes) + .compose(t3.changes) + .compose(t4.changes) + .compose(t5.changes); + + use Operation::*; + assert_eq!(changes.changes, &[Insert("hello".into())]); + } }