@@ -103,23 +103,23 @@ fn interpolate(
) -> Option<Vec<(Range<Anchor>, String)>> {
let mut edits = Vec::new();
- let mut model_edits = current_edits.into_iter().peekable();
- for user_edit in new_snapshot.edits_since::<usize>(&old_snapshot.version) {
- while let Some((model_old_range, _)) = model_edits.peek() {
- let model_old_range = model_old_range.to_offset(old_snapshot);
- if !model_old_range.is_empty() {
- return None;
- } else if model_old_range.end < user_edit.old.start {
- let (model_old_range, model_new_text) = model_edits.next().unwrap();
- edits.push((model_old_range.clone(), model_new_text.clone()));
+ let mut user_edits = new_snapshot
+ .edits_since::<usize>(&old_snapshot.version)
+ .peekable();
+ for (model_old_range, model_new_text) in current_edits.iter() {
+ let model_offset_range = model_old_range.to_offset(old_snapshot);
+ while let Some(next_user_edit) = user_edits.peek() {
+ if next_user_edit.old.end < model_offset_range.start {
+ user_edits.next();
} else {
break;
}
}
- if let Some((model_old_range, model_new_text)) = model_edits.peek() {
- let model_old_offset_range = model_old_range.to_offset(old_snapshot);
- if user_edit.old == model_old_offset_range {
+ if let Some(user_edit) = user_edits.peek() {
+ if user_edit.old.start > model_offset_range.end {
+ edits.push((model_old_range.clone(), model_new_text.clone()));
+ } else if user_edit.old == model_offset_range {
let user_new_text = new_snapshot
.text_for_range(user_edit.new.clone())
.collect::<String>();
@@ -128,26 +128,20 @@ fn interpolate(
if !model_suffix.is_empty() {
edits.push((
new_snapshot.anchor_after(user_edit.new.end)
- ..new_snapshot.anchor_after(user_edit.new.end),
- model_suffix.to_string(),
+ ..new_snapshot.anchor_before(user_edit.new.end),
+ model_suffix.into(),
));
}
- model_edits.next();
- continue;
+ user_edits.next();
+ } else {
+ return None;
}
+ } else {
+ return None;
}
- }
-
- return None;
- }
-
- for (model_old_range, model_new_text) in model_edits {
- let model_old_offset_range = model_old_range.to_offset(old_snapshot);
- if model_old_offset_range.is_empty() {
- edits.push((model_old_range.clone(), model_new_text.clone()));
} else {
- return None;
+ edits.push((model_old_range.clone(), model_new_text.clone()));
}
}
@@ -1283,10 +1277,10 @@ mod tests {
#[gpui::test]
async fn test_inline_completion_basic_interpolation(cx: &mut TestAppContext) {
- let buffer = cx.new(|cx| Buffer::local("Lo ips dolor", cx));
+ let buffer = cx.new(|cx| Buffer::local("Lorem ipsum dolor", cx));
let edits: Arc<[(Range<Anchor>, String)]> = cx.update(|cx| {
to_completion_edits(
- [(2..2, "REM".to_string()), (6..6, "UM".to_string())],
+ [(2..5, "REM".to_string()), (9..11, "".to_string())],
&buffer,
cx,
)
@@ -1320,55 +1314,80 @@ mod tests {
&buffer,
cx
),
- vec![(2..2, "REM".to_string()), (6..6, "UM".to_string())]
+ vec![(2..5, "REM".to_string()), (9..11, "".to_string())]
);
- buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "R")], None, cx));
+ buffer.update(cx, |buffer, cx| buffer.edit([(2..5, "")], None, cx));
assert_eq!(
from_completion_edits(
&completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
&buffer,
cx
),
- vec![(3..3, "EM".to_string()), (7..7, "UM".to_string())]
+ vec![(2..2, "REM".to_string()), (6..8, "".to_string())]
);
- buffer.update(cx, |buffer, cx| buffer.edit([(7..7, "U")], None, cx));
+ buffer.update(cx, |buffer, cx| buffer.undo(cx));
assert_eq!(
from_completion_edits(
&completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
&buffer,
cx
),
- vec![(3..3, "EM".to_string()), (8..8, "M".to_string())]
+ vec![(2..5, "REM".to_string()), (9..11, "".to_string())]
);
- // Editing after all the model edits should always keep the inline completion
- buffer.update(cx, |buffer, cx| buffer.edit([(10..10, "X")], None, cx));
- assert_eq!(completion.interpolate(&buffer.read(cx).snapshot()), None);
+ buffer.update(cx, |buffer, cx| buffer.edit([(2..5, "R")], None, cx));
+ assert_eq!(
+ from_completion_edits(
+ &completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
+ &buffer,
+ cx
+ ),
+ vec![(3..3, "EM".to_string()), (7..9, "".to_string())]
+ );
- buffer.update(cx, |buffer, cx| buffer.undo(cx));
+ buffer.update(cx, |buffer, cx| buffer.edit([(3..3, "E")], None, cx));
+ assert_eq!(
+ from_completion_edits(
+ &completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
+ &buffer,
+ cx
+ ),
+ vec![(4..4, "M".to_string()), (8..10, "".to_string())]
+ );
+
+ buffer.update(cx, |buffer, cx| buffer.edit([(4..4, "M")], None, cx));
+ assert_eq!(
+ from_completion_edits(
+ &completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
+ &buffer,
+ cx
+ ),
+ vec![(9..11, "".to_string())]
+ );
+
+ buffer.update(cx, |buffer, cx| buffer.edit([(4..5, "")], None, cx));
assert_eq!(
from_completion_edits(
&completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
&buffer,
cx
),
- vec![(3..3, "EM".to_string()), (8..8, "M".to_string())]
+ vec![(4..4, "M".to_string()), (8..10, "".to_string())]
);
- buffer.update(cx, |buffer, cx| buffer.edit([(8..8, "M")], None, cx));
+ buffer.update(cx, |buffer, cx| buffer.edit([(8..10, "")], None, cx));
assert_eq!(
from_completion_edits(
&completion.interpolate(&buffer.read(cx).snapshot()).unwrap(),
&buffer,
cx
),
- vec![(3..3, "EM".to_string())]
+ vec![(4..4, "M".to_string())]
);
- // Editing before the model edits should always remove the inline completion
- buffer.update(cx, |buffer, cx| buffer.edit([(0..0, "I")], None, cx));
+ buffer.update(cx, |buffer, cx| buffer.edit([(4..6, "")], None, cx));
assert_eq!(completion.interpolate(&buffer.read(cx).snapshot()), None);
})
}