Compute diffs based on characters rather than lines
Previously, a change on a given line would cause that whole line to be replaced. In turn, this caused anchors on that line to go to the start of that line because they would lie inside of a deleted region after applying the diff. By switching to a character-wise diff, we perform smaller edits to the buffer which stabilizes anchor positions.
This commit is contained in:
parent
f7a3141576
commit
71128d2ee6
2 changed files with 6 additions and 3 deletions
|
@ -1006,7 +1006,7 @@ 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_lines(old_text.as_str(), new_text.as_str())
|
let changes = TextDiff::from_chars(old_text.as_str(), new_text.as_str())
|
||||||
.iter_all_changes()
|
.iter_all_changes()
|
||||||
.map(|c| (c.tag(), c.value().len()))
|
.map(|c| (c.tag(), c.value().len()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -183,20 +183,23 @@ fn test_edit_events(cx: &mut gpui::MutableAppContext) {
|
||||||
async fn test_apply_diff(cx: &mut gpui::TestAppContext) {
|
async fn test_apply_diff(cx: &mut gpui::TestAppContext) {
|
||||||
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
|
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
|
||||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||||
|
let anchor = buffer.read_with(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
|
||||||
|
|
||||||
let text = "a\nccc\ndddd\nffffff\n";
|
let text = "a\nccc\ndddd\nffffff\n";
|
||||||
let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
|
let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
|
||||||
buffer.update(cx, |buffer, cx| {
|
buffer.update(cx, |buffer, cx| {
|
||||||
buffer.apply_diff(diff, cx).unwrap();
|
buffer.apply_diff(diff, cx).unwrap();
|
||||||
|
assert_eq!(buffer.text(), text);
|
||||||
|
assert_eq!(anchor.to_point(&buffer), Point::new(2, 3));
|
||||||
});
|
});
|
||||||
cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
|
|
||||||
|
|
||||||
let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
|
let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
|
||||||
let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
|
let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
|
||||||
buffer.update(cx, |buffer, cx| {
|
buffer.update(cx, |buffer, cx| {
|
||||||
buffer.apply_diff(diff, cx).unwrap();
|
buffer.apply_diff(diff, cx).unwrap();
|
||||||
|
assert_eq!(buffer.text(), text);
|
||||||
|
assert_eq!(anchor.to_point(&buffer), Point::new(4, 4));
|
||||||
});
|
});
|
||||||
cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue