Merge pull request #1689 from zed-industries/optimize-buffer-diff

Apply buffer diff edits as a single batch
This commit is contained in:
Max Brunsfeld 2022-10-06 12:28:42 -07:00 committed by GitHub
commit c0ee8dc007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

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