Apply buffer diff edits as a single batch
This commit is contained in:
parent
51fa06cc8d
commit
fe7a39ba5c
1 changed files with 23 additions and 32 deletions
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue