transaction: Merge consecutive inserts on compose.

This commit is contained in:
Blaž Hrastnik 2021-02-16 00:15:49 +09:00
parent 65893a2cbc
commit 19fb4ed835

View file

@ -94,8 +94,14 @@ impl ChangeSet {
head_b = b; head_b = b;
} }
// insertion in B // insertion in B
(a, Some(change @ Insert(..))) => { (a, Some(Insert(current))) => {
changes.push(change); // 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(&current);
} else {
changes.push(Insert(current));
}
head_a = a; head_a = a;
head_b = changes_b.next(); head_b = changes_b.next();
} }
@ -422,7 +428,9 @@ impl Transaction {
let mut last = 0; let mut last = 0;
for (from, to, tendril) in changes { for (from, to, tendril) in changes {
// Retain from last "to" to current "from" // 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; let span = to - from;
match tendril { match tendril {
Some(text) => { Some(text) => {
@ -581,4 +589,36 @@ mod test {
transaction.apply(&mut state); transaction.apply(&mut state);
assert_eq!(state.doc, Rope::from_str("hello void! 123")); 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())]);
}
} }