Apply buffer diff edits as a single batch

This commit is contained in:
Max Brunsfeld 2022-10-06 11:54:28 -07:00
parent 51fa06cc8d
commit fe7a39ba5c

View file

@ -300,10 +300,8 @@ pub struct Chunk<'a> {
pub struct Diff { pub struct Diff {
base_version: clock::Global, base_version: clock::Global,
new_text: Arc<str>,
changes: Vec<(ChangeTag, usize)>,
line_ending: LineEnding, line_ending: LineEnding,
start_offset: usize, edits: Vec<(Range<usize>, Arc<str>)>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -1084,16 +1082,30 @@ impl Buffer {
let old_text = old_text.to_string(); let old_text = old_text.to_string();
let line_ending = LineEnding::detect(&new_text); let line_ending = LineEnding::detect(&new_text);
LineEnding::normalize(&mut new_text); LineEnding::normalize(&mut new_text);
let changes = TextDiff::from_chars(old_text.as_str(), new_text.as_str()) let diff = TextDiff::from_chars(old_text.as_str(), new_text.as_str());
.iter_all_changes() let mut edits = Vec::new();
.map(|c| (c.tag(), c.value().len())) let mut offset = 0;
.collect::<Vec<_>>(); let empty: Arc<str> = "".into();
for change in diff.iter_all_changes() {
let value = change.value();
let end_offset = offset + value.len();
match change.tag() {
ChangeTag::Equal => {
offset = end_offset;
}
ChangeTag::Delete => {
edits.push((offset..end_offset, empty.clone()));
offset = end_offset;
}
ChangeTag::Insert => {
edits.push((offset..offset, value.into()));
}
}
}
Diff { Diff {
base_version, base_version,
new_text: new_text.into(),
changes,
line_ending, line_ending,
start_offset: 0, edits,
} }
}) })
} }
@ -1103,28 +1115,7 @@ impl Buffer {
self.finalize_last_transaction(); self.finalize_last_transaction();
self.start_transaction(); self.start_transaction();
self.text.set_line_ending(diff.line_ending); self.text.set_line_ending(diff.line_ending);
let mut offset = diff.start_offset; self.edit(diff.edits, None, cx);
for (tag, len) in diff.changes {
let range = offset..(offset + len);
match tag {
ChangeTag::Equal => offset += len,
ChangeTag::Delete => {
self.edit([(range, "")], None, cx);
}
ChangeTag::Insert => {
self.edit(
[(
offset..offset,
&diff.new_text[range.start - diff.start_offset
..range.end - diff.start_offset],
)],
None,
cx,
);
offset += len;
}
}
}
if self.end_transaction(cx).is_some() { if self.end_transaction(cx).is_some() {
self.finalize_last_transaction() self.finalize_last_transaction()
} else { } else {