@@ -6523,6 +6523,10 @@ impl Editor {
provider.accept(cx);
}
+ // Store the transaction ID and selections before applying the edit
+ let transaction_id_prev =
+ self.buffer.read_with(cx, |b, cx| b.last_transaction_id(cx));
+
let snapshot = self.buffer.read(cx).snapshot(cx);
let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
@@ -6531,9 +6535,20 @@ impl Editor {
});
self.change_selections(None, window, cx, |s| {
- s.select_anchor_ranges([last_edit_end..last_edit_end])
+ s.select_anchor_ranges([last_edit_end..last_edit_end]);
});
+ let selections = self.selections.disjoint_anchors();
+ if let Some(transaction_id_now) =
+ self.buffer.read_with(cx, |b, cx| b.last_transaction_id(cx))
+ {
+ let has_new_transaction = transaction_id_prev != Some(transaction_id_now);
+ if has_new_transaction {
+ self.selection_history
+ .insert_transaction(transaction_id_now, selections);
+ }
+ }
+
self.update_visible_inline_completion(window, cx);
if self.active_inline_completion.is_none() {
self.refresh_inline_completion(true, true, window, cx);
@@ -1,6 +1,7 @@
use super::*;
use crate::{
JoinLines,
+ inline_completion_tests::FakeInlineCompletionProvider,
linked_editing_ranges::LinkedEditingRanges,
scroll::scroll_amount::ScrollAmount,
test::{
@@ -6380,6 +6381,98 @@ async fn test_undo_format_scrolls_to_last_edit_pos(cx: &mut TestAppContext) {
"});
}
+#[gpui::test]
+async fn test_undo_inline_completion_scrolls_to_edit_pos(cx: &mut TestAppContext) {
+ init_test(cx, |_| {});
+
+ let mut cx = EditorTestContext::new(cx).await;
+
+ let provider = cx.new(|_| FakeInlineCompletionProvider::default());
+ cx.update_editor(|editor, window, cx| {
+ editor.set_edit_prediction_provider(Some(provider.clone()), window, cx);
+ });
+
+ cx.set_state(indoc! {"
+ line 1
+ line 2
+ linˇe 3
+ line 4
+ line 5
+ line 6
+ line 7
+ line 8
+ line 9
+ line 10
+ "});
+
+ let snapshot = cx.buffer_snapshot();
+ let edit_position = snapshot.anchor_after(Point::new(2, 4));
+
+ cx.update(|_, cx| {
+ provider.update(cx, |provider, _| {
+ provider.set_inline_completion(Some(inline_completion::InlineCompletion {
+ id: None,
+ edits: vec![(edit_position..edit_position, "X".into())],
+ edit_preview: None,
+ }))
+ })
+ });
+
+ cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx));
+ cx.update_editor(|editor, window, cx| {
+ editor.accept_edit_prediction(&crate::AcceptEditPrediction, window, cx)
+ });
+
+ cx.assert_editor_state(indoc! {"
+ line 1
+ line 2
+ lineXˇ 3
+ line 4
+ line 5
+ line 6
+ line 7
+ line 8
+ line 9
+ line 10
+ "});
+
+ cx.update_editor(|editor, window, cx| {
+ editor.change_selections(None, window, cx, |s| {
+ s.select_ranges([Point::new(9, 2)..Point::new(9, 2)]);
+ });
+ });
+
+ cx.assert_editor_state(indoc! {"
+ line 1
+ line 2
+ lineX 3
+ line 4
+ line 5
+ line 6
+ line 7
+ line 8
+ line 9
+ liˇne 10
+ "});
+
+ cx.update_editor(|editor, window, cx| {
+ editor.undo(&Default::default(), window, cx);
+ });
+
+ cx.assert_editor_state(indoc! {"
+ line 1
+ line 2
+ lineˇ 3
+ line 4
+ line 5
+ line 6
+ line 7
+ line 8
+ line 9
+ line 10
+ "});
+}
+
#[gpui::test]
async fn test_select_next_with_multiple_carets(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -302,8 +302,8 @@ fn assign_editor_completion_provider(
}
#[derive(Default, Clone)]
-struct FakeInlineCompletionProvider {
- completion: Option<inline_completion::InlineCompletion>,
+pub struct FakeInlineCompletionProvider {
+ pub completion: Option<inline_completion::InlineCompletion>,
}
impl FakeInlineCompletionProvider {