editor_tests.rs

   1use gpui::TestAppContext;
   2use language::language_settings::{AllLanguageSettings, AllLanguageSettingsContent};
   3use settings::SettingsStore;
   4
   5// use super::*;
   6// use crate::{
   7//     scroll::scroll_amount::ScrollAmount,
   8//     test::{
   9//         assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
  10//         editor_test_context::EditorTestContext, select_ranges,
  11//     },
  12//     JoinLines,
  13// };
  14// use drag_and_drop::DragAndDrop;
  15// use futures::StreamExt;
  16// use gpui::{
  17//     executor::Deterministic,
  18//     geometry::{rect::RectF, vector::vec2f},
  19//     platform::{WindowBounds, WindowOptions},
  20//     serde_json::{self, json},
  21//     TestAppContext,
  22// };
  23// use indoc::indoc;
  24// use language::{
  25//     language_settings::{AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent},
  26//     BracketPairConfig, FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry,
  27//     Override, Point,
  28// };
  29// use parking_lot::Mutex;
  30// use project::project_settings::{LspSettings, ProjectSettings};
  31// use project::FakeFs;
  32// use std::sync::atomic;
  33// use std::sync::atomic::AtomicUsize;
  34// use std::{cell::RefCell, future::Future, rc::Rc, time::Instant};
  35// use unindent::Unindent;
  36// use util::{
  37//     assert_set_eq,
  38//     test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
  39// };
  40// use workspace::{
  41//     item::{FollowableItem, Item, ItemHandle},
  42//     NavigationEntry, ViewId,
  43// };
  44
  45// #[gpui::test]
  46// fn test_edit_events(cx: &mut TestAppContext) {
  47//     init_test(cx, |_| {});
  48
  49//     let buffer = cx.add_model(|cx| {
  50//         let mut buffer = language::Buffer::new(0, cx.model_id() as u64, "123456");
  51//         buffer.set_group_interval(Duration::from_secs(1));
  52//         buffer
  53//     });
  54
  55//     let events = Rc::new(RefCell::new(Vec::new()));
  56//     let editor1 = cx
  57//         .add_window({
  58//             let events = events.clone();
  59//             |cx| {
  60//                 cx.subscribe(&cx.handle(), move |_, _, event, _| {
  61//                     if matches!(
  62//                         event,
  63//                         Event::Edited | Event::BufferEdited | Event::DirtyChanged
  64//                     ) {
  65//                         events.borrow_mut().push(("editor1", event.clone()));
  66//                     }
  67//                 })
  68//                 .detach();
  69//                 Editor::for_buffer(buffer.clone(), None, cx)
  70//             }
  71//         })
  72//         .root(cx);
  73//     let editor2 = cx
  74//         .add_window({
  75//             let events = events.clone();
  76//             |cx| {
  77//                 cx.subscribe(&cx.handle(), move |_, _, event, _| {
  78//                     if matches!(
  79//                         event,
  80//                         Event::Edited | Event::BufferEdited | Event::DirtyChanged
  81//                     ) {
  82//                         events.borrow_mut().push(("editor2", event.clone()));
  83//                     }
  84//                 })
  85//                 .detach();
  86//                 Editor::for_buffer(buffer.clone(), None, cx)
  87//             }
  88//         })
  89//         .root(cx);
  90//     assert_eq!(mem::take(&mut *events.borrow_mut()), []);
  91
  92//     // Mutating editor 1 will emit an `Edited` event only for that editor.
  93//     editor1.update(cx, |editor, cx| editor.insert("X", cx));
  94//     assert_eq!(
  95//         mem::take(&mut *events.borrow_mut()),
  96//         [
  97//             ("editor1", Event::Edited),
  98//             ("editor1", Event::BufferEdited),
  99//             ("editor2", Event::BufferEdited),
 100//             ("editor1", Event::DirtyChanged),
 101//             ("editor2", Event::DirtyChanged)
 102//         ]
 103//     );
 104
 105//     // Mutating editor 2 will emit an `Edited` event only for that editor.
 106//     editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 107//     assert_eq!(
 108//         mem::take(&mut *events.borrow_mut()),
 109//         [
 110//             ("editor2", Event::Edited),
 111//             ("editor1", Event::BufferEdited),
 112//             ("editor2", Event::BufferEdited),
 113//         ]
 114//     );
 115
 116//     // Undoing on editor 1 will emit an `Edited` event only for that editor.
 117//     editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 118//     assert_eq!(
 119//         mem::take(&mut *events.borrow_mut()),
 120//         [
 121//             ("editor1", Event::Edited),
 122//             ("editor1", Event::BufferEdited),
 123//             ("editor2", Event::BufferEdited),
 124//             ("editor1", Event::DirtyChanged),
 125//             ("editor2", Event::DirtyChanged),
 126//         ]
 127//     );
 128
 129//     // Redoing on editor 1 will emit an `Edited` event only for that editor.
 130//     editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 131//     assert_eq!(
 132//         mem::take(&mut *events.borrow_mut()),
 133//         [
 134//             ("editor1", Event::Edited),
 135//             ("editor1", Event::BufferEdited),
 136//             ("editor2", Event::BufferEdited),
 137//             ("editor1", Event::DirtyChanged),
 138//             ("editor2", Event::DirtyChanged),
 139//         ]
 140//     );
 141
 142//     // Undoing on editor 2 will emit an `Edited` event only for that editor.
 143//     editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 144//     assert_eq!(
 145//         mem::take(&mut *events.borrow_mut()),
 146//         [
 147//             ("editor2", Event::Edited),
 148//             ("editor1", Event::BufferEdited),
 149//             ("editor2", Event::BufferEdited),
 150//             ("editor1", Event::DirtyChanged),
 151//             ("editor2", Event::DirtyChanged),
 152//         ]
 153//     );
 154
 155//     // Redoing on editor 2 will emit an `Edited` event only for that editor.
 156//     editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 157//     assert_eq!(
 158//         mem::take(&mut *events.borrow_mut()),
 159//         [
 160//             ("editor2", Event::Edited),
 161//             ("editor1", Event::BufferEdited),
 162//             ("editor2", Event::BufferEdited),
 163//             ("editor1", Event::DirtyChanged),
 164//             ("editor2", Event::DirtyChanged),
 165//         ]
 166//     );
 167
 168//     // No event is emitted when the mutation is a no-op.
 169//     editor2.update(cx, |editor, cx| {
 170//         editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 171
 172//         editor.backspace(&Backspace, cx);
 173//     });
 174//     assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 175// }
 176
 177// #[gpui::test]
 178// fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
 179//     init_test(cx, |_| {});
 180
 181//     let mut now = Instant::now();
 182//     let buffer = cx.add_model(|cx| language::Buffer::new(0, cx.model_id() as u64, "123456"));
 183//     let group_interval = buffer.read_with(cx, |buffer, _| buffer.transaction_group_interval());
 184//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 185//     let editor = cx
 186//         .add_window(|cx| build_editor(buffer.clone(), cx))
 187//         .root(cx);
 188
 189//     editor.update(cx, |editor, cx| {
 190//         editor.start_transaction_at(now, cx);
 191//         editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 192
 193//         editor.insert("cd", cx);
 194//         editor.end_transaction_at(now, cx);
 195//         assert_eq!(editor.text(cx), "12cd56");
 196//         assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 197
 198//         editor.start_transaction_at(now, cx);
 199//         editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 200//         editor.insert("e", cx);
 201//         editor.end_transaction_at(now, cx);
 202//         assert_eq!(editor.text(cx), "12cde6");
 203//         assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 204
 205//         now += group_interval + Duration::from_millis(1);
 206//         editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 207
 208//         // Simulate an edit in another editor
 209//         buffer.update(cx, |buffer, cx| {
 210//             buffer.start_transaction_at(now, cx);
 211//             buffer.edit([(0..1, "a")], None, cx);
 212//             buffer.edit([(1..1, "b")], None, cx);
 213//             buffer.end_transaction_at(now, cx);
 214//         });
 215
 216//         assert_eq!(editor.text(cx), "ab2cde6");
 217//         assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 218
 219//         // Last transaction happened past the group interval in a different editor.
 220//         // Undo it individually and don't restore selections.
 221//         editor.undo(&Undo, cx);
 222//         assert_eq!(editor.text(cx), "12cde6");
 223//         assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 224
 225//         // First two transactions happened within the group interval in this editor.
 226//         // Undo them together and restore selections.
 227//         editor.undo(&Undo, cx);
 228//         editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 229//         assert_eq!(editor.text(cx), "123456");
 230//         assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 231
 232//         // Redo the first two transactions together.
 233//         editor.redo(&Redo, cx);
 234//         assert_eq!(editor.text(cx), "12cde6");
 235//         assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 236
 237//         // Redo the last transaction on its own.
 238//         editor.redo(&Redo, cx);
 239//         assert_eq!(editor.text(cx), "ab2cde6");
 240//         assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 241
 242//         // Test empty transactions.
 243//         editor.start_transaction_at(now, cx);
 244//         editor.end_transaction_at(now, cx);
 245//         editor.undo(&Undo, cx);
 246//         assert_eq!(editor.text(cx), "12cde6");
 247//     });
 248// }
 249
 250// #[gpui::test]
 251// fn test_ime_composition(cx: &mut TestAppContext) {
 252//     init_test(cx, |_| {});
 253
 254//     let buffer = cx.add_model(|cx| {
 255//         let mut buffer = language::Buffer::new(0, cx.model_id() as u64, "abcde");
 256//         // Ensure automatic grouping doesn't occur.
 257//         buffer.set_group_interval(Duration::ZERO);
 258//         buffer
 259//     });
 260
 261//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 262//     cx.add_window(|cx| {
 263//         let mut editor = build_editor(buffer.clone(), cx);
 264
 265//         // Start a new IME composition.
 266//         editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 267//         editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 268//         editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 269//         assert_eq!(editor.text(cx), "äbcde");
 270//         assert_eq!(
 271//             editor.marked_text_ranges(cx),
 272//             Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 273//         );
 274
 275//         // Finalize IME composition.
 276//         editor.replace_text_in_range(None, "ā", cx);
 277//         assert_eq!(editor.text(cx), "ābcde");
 278//         assert_eq!(editor.marked_text_ranges(cx), None);
 279
 280//         // IME composition edits are grouped and are undone/redone at once.
 281//         editor.undo(&Default::default(), cx);
 282//         assert_eq!(editor.text(cx), "abcde");
 283//         assert_eq!(editor.marked_text_ranges(cx), None);
 284//         editor.redo(&Default::default(), cx);
 285//         assert_eq!(editor.text(cx), "ābcde");
 286//         assert_eq!(editor.marked_text_ranges(cx), None);
 287
 288//         // Start a new IME composition.
 289//         editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 290//         assert_eq!(
 291//             editor.marked_text_ranges(cx),
 292//             Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 293//         );
 294
 295//         // Undoing during an IME composition cancels it.
 296//         editor.undo(&Default::default(), cx);
 297//         assert_eq!(editor.text(cx), "ābcde");
 298//         assert_eq!(editor.marked_text_ranges(cx), None);
 299
 300//         // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 301//         editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 302//         assert_eq!(editor.text(cx), "ābcdè");
 303//         assert_eq!(
 304//             editor.marked_text_ranges(cx),
 305//             Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 306//         );
 307
 308//         // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 309//         editor.replace_text_in_range(Some(4..999), "ę", cx);
 310//         assert_eq!(editor.text(cx), "ābcdę");
 311//         assert_eq!(editor.marked_text_ranges(cx), None);
 312
 313//         // Start a new IME composition with multiple cursors.
 314//         editor.change_selections(None, cx, |s| {
 315//             s.select_ranges([
 316//                 OffsetUtf16(1)..OffsetUtf16(1),
 317//                 OffsetUtf16(3)..OffsetUtf16(3),
 318//                 OffsetUtf16(5)..OffsetUtf16(5),
 319//             ])
 320//         });
 321//         editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 322//         assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 323//         assert_eq!(
 324//             editor.marked_text_ranges(cx),
 325//             Some(vec![
 326//                 OffsetUtf16(0)..OffsetUtf16(3),
 327//                 OffsetUtf16(4)..OffsetUtf16(7),
 328//                 OffsetUtf16(8)..OffsetUtf16(11)
 329//             ])
 330//         );
 331
 332//         // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 333//         editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 334//         assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 335//         assert_eq!(
 336//             editor.marked_text_ranges(cx),
 337//             Some(vec![
 338//                 OffsetUtf16(1)..OffsetUtf16(2),
 339//                 OffsetUtf16(5)..OffsetUtf16(6),
 340//                 OffsetUtf16(9)..OffsetUtf16(10)
 341//             ])
 342//         );
 343
 344//         // Finalize IME composition with multiple cursors.
 345//         editor.replace_text_in_range(Some(9..10), "2", cx);
 346//         assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 347//         assert_eq!(editor.marked_text_ranges(cx), None);
 348
 349//         editor
 350//     });
 351// }
 352
 353// #[gpui::test]
 354// fn test_selection_with_mouse(cx: &mut TestAppContext) {
 355//     init_test(cx, |_| {});
 356
 357//     let editor = cx
 358//         .add_window(|cx| {
 359//             let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 360//             build_editor(buffer, cx)
 361//         })
 362//         .root(cx);
 363//     editor.update(cx, |view, cx| {
 364//         view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 365//     });
 366//     assert_eq!(
 367//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 368//         [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 369//     );
 370
 371//     editor.update(cx, |view, cx| {
 372//         view.update_selection(DisplayPoint::new(3, 3), 0, Point<Pixels>::zero(), cx);
 373//     });
 374
 375//     assert_eq!(
 376//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 377//         [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 378//     );
 379
 380//     editor.update(cx, |view, cx| {
 381//         view.update_selection(DisplayPoint::new(1, 1), 0, Point<Pixels>::zero(), cx);
 382//     });
 383
 384//     assert_eq!(
 385//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 386//         [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 387//     );
 388
 389//     editor.update(cx, |view, cx| {
 390//         view.end_selection(cx);
 391//         view.update_selection(DisplayPoint::new(3, 3), 0, Point<Pixels>::zero(), cx);
 392//     });
 393
 394//     assert_eq!(
 395//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 396//         [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 397//     );
 398
 399//     editor.update(cx, |view, cx| {
 400//         view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 401//         view.update_selection(DisplayPoint::new(0, 0), 0, Point<Pixels>::zero(), cx);
 402//     });
 403
 404//     assert_eq!(
 405//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 406//         [
 407//             DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 408//             DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 409//         ]
 410//     );
 411
 412//     editor.update(cx, |view, cx| {
 413//         view.end_selection(cx);
 414//     });
 415
 416//     assert_eq!(
 417//         editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 418//         [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 419//     );
 420// }
 421
 422// #[gpui::test]
 423// fn test_canceling_pending_selection(cx: &mut TestAppContext) {
 424//     init_test(cx, |_| {});
 425
 426//     let view = cx
 427//         .add_window(|cx| {
 428//             let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 429//             build_editor(buffer, cx)
 430//         })
 431//         .root(cx);
 432
 433//     view.update(cx, |view, cx| {
 434//         view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 435//         assert_eq!(
 436//             view.selections.display_ranges(cx),
 437//             [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 438//         );
 439//     });
 440
 441//     view.update(cx, |view, cx| {
 442//         view.update_selection(DisplayPoint::new(3, 3), 0, Point<Pixels>::zero(), cx);
 443//         assert_eq!(
 444//             view.selections.display_ranges(cx),
 445//             [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 446//         );
 447//     });
 448
 449//     view.update(cx, |view, cx| {
 450//         view.cancel(&Cancel, cx);
 451//         view.update_selection(DisplayPoint::new(1, 1), 0, Point<Pixels>::zero(), cx);
 452//         assert_eq!(
 453//             view.selections.display_ranges(cx),
 454//             [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 455//         );
 456//     });
 457// }
 458
 459// #[gpui::test]
 460// fn test_clone(cx: &mut TestAppContext) {
 461//     init_test(cx, |_| {});
 462
 463//     let (text, selection_ranges) = marked_text_ranges(
 464//         indoc! {"
 465//             one
 466//             two
 467//             threeˇ
 468//             four
 469//             fiveˇ
 470//         "},
 471//         true,
 472//     );
 473
 474//     let editor = cx
 475//         .add_window(|cx| {
 476//             let buffer = MultiBuffer::build_simple(&text, cx);
 477//             build_editor(buffer, cx)
 478//         })
 479//         .root(cx);
 480
 481//     editor.update(cx, |editor, cx| {
 482//         editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 483//         editor.fold_ranges(
 484//             [
 485//                 Point::new(1, 0)..Point::new(2, 0),
 486//                 Point::new(3, 0)..Point::new(4, 0),
 487//             ],
 488//             true,
 489//             cx,
 490//         );
 491//     });
 492
 493//     let cloned_editor = editor
 494//         .update(cx, |editor, cx| {
 495//             cx.add_window(Default::default(), |cx| editor.clone(cx))
 496//         })
 497//         .root(cx);
 498
 499//     let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 500//     let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 501
 502//     assert_eq!(
 503//         cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 504//         editor.update(cx, |e, cx| e.display_text(cx))
 505//     );
 506//     assert_eq!(
 507//         cloned_snapshot
 508//             .folds_in_range(0..text.len())
 509//             .collect::<Vec<_>>(),
 510//         snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 511//     );
 512//     assert_set_eq!(
 513//         cloned_editor.read_with(cx, |editor, cx| editor.selections.ranges::<Point>(cx)),
 514//         editor.read_with(cx, |editor, cx| editor.selections.ranges(cx))
 515//     );
 516//     assert_set_eq!(
 517//         cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 518//         editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 519//     );
 520// }
 521
 522// #[gpui::test]
 523// async fn test_navigation_history(cx: &mut TestAppContext) {
 524//     init_test(cx, |_| {});
 525
 526//     cx.set_global(DragAndDrop::<Workspace>::default());
 527//     use workspace::item::Item;
 528
 529//     let fs = FakeFs::new(cx.background());
 530//     let project = Project::test(fs, [], cx).await;
 531//     let window = cx.add_window(|cx| Workspace::test_new(project, cx));
 532//     let workspace = window.root(cx);
 533//     let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
 534//     window.add_view(cx, |cx| {
 535//         let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 536//         let mut editor = build_editor(buffer.clone(), cx);
 537//         let handle = cx.handle();
 538//         editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 539
 540//         fn pop_history(editor: &mut Editor, cx: &mut WindowContext) -> Option<NavigationEntry> {
 541//             editor.nav_history.as_mut().unwrap().pop_backward(cx)
 542//         }
 543
 544//         // Move the cursor a small distance.
 545//         // Nothing is added to the navigation history.
 546//         editor.change_selections(None, cx, |s| {
 547//             s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 548//         });
 549//         editor.change_selections(None, cx, |s| {
 550//             s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 551//         });
 552//         assert!(pop_history(&mut editor, cx).is_none());
 553
 554//         // Move the cursor a large distance.
 555//         // The history can jump back to the previous position.
 556//         editor.change_selections(None, cx, |s| {
 557//             s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 558//         });
 559//         let nav_entry = pop_history(&mut editor, cx).unwrap();
 560//         editor.navigate(nav_entry.data.unwrap(), cx);
 561//         assert_eq!(nav_entry.item.id(), cx.view_id());
 562//         assert_eq!(
 563//             editor.selections.display_ranges(cx),
 564//             &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 565//         );
 566//         assert!(pop_history(&mut editor, cx).is_none());
 567
 568//         // Move the cursor a small distance via the mouse.
 569//         // Nothing is added to the navigation history.
 570//         editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 571//         editor.end_selection(cx);
 572//         assert_eq!(
 573//             editor.selections.display_ranges(cx),
 574//             &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 575//         );
 576//         assert!(pop_history(&mut editor, cx).is_none());
 577
 578//         // Move the cursor a large distance via the mouse.
 579//         // The history can jump back to the previous position.
 580//         editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 581//         editor.end_selection(cx);
 582//         assert_eq!(
 583//             editor.selections.display_ranges(cx),
 584//             &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 585//         );
 586//         let nav_entry = pop_history(&mut editor, cx).unwrap();
 587//         editor.navigate(nav_entry.data.unwrap(), cx);
 588//         assert_eq!(nav_entry.item.id(), cx.view_id());
 589//         assert_eq!(
 590//             editor.selections.display_ranges(cx),
 591//             &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 592//         );
 593//         assert!(pop_history(&mut editor, cx).is_none());
 594
 595//         // Set scroll position to check later
 596//         editor.set_scroll_position(Point<Pixels>::new(5.5, 5.5), cx);
 597//         let original_scroll_position = editor.scroll_manager.anchor();
 598
 599//         // Jump to the end of the document and adjust scroll
 600//         editor.move_to_end(&MoveToEnd, cx);
 601//         editor.set_scroll_position(Point<Pixels>::new(-2.5, -0.5), cx);
 602//         assert_ne!(editor.scroll_manager.anchor(), original_scroll_position);
 603
 604//         let nav_entry = pop_history(&mut editor, cx).unwrap();
 605//         editor.navigate(nav_entry.data.unwrap(), cx);
 606//         assert_eq!(editor.scroll_manager.anchor(), original_scroll_position);
 607
 608//         // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 609//         let mut invalid_anchor = editor.scroll_manager.anchor().anchor;
 610//         invalid_anchor.text_anchor.buffer_id = Some(999);
 611//         let invalid_point = Point::new(9999, 0);
 612//         editor.navigate(
 613//             Box::new(NavigationData {
 614//                 cursor_anchor: invalid_anchor,
 615//                 cursor_position: invalid_point,
 616//                 scroll_anchor: ScrollAnchor {
 617//                     anchor: invalid_anchor,
 618//                     offset: Default::default(),
 619//                 },
 620//                 scroll_top_row: invalid_point.row,
 621//             }),
 622//             cx,
 623//         );
 624//         assert_eq!(
 625//             editor.selections.display_ranges(cx),
 626//             &[editor.max_point(cx)..editor.max_point(cx)]
 627//         );
 628//         assert_eq!(
 629//             editor.scroll_position(cx),
 630//             vec2f(0., editor.max_point(cx).row() as f32)
 631//         );
 632
 633//         editor
 634//     });
 635// }
 636
 637// #[gpui::test]
 638// fn test_cancel(cx: &mut TestAppContext) {
 639//     init_test(cx, |_| {});
 640
 641//     let view = cx
 642//         .add_window(|cx| {
 643//             let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 644//             build_editor(buffer, cx)
 645//         })
 646//         .root(cx);
 647
 648//     view.update(cx, |view, cx| {
 649//         view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 650//         view.update_selection(DisplayPoint::new(1, 1), 0, Point<Pixels>::zero(), cx);
 651//         view.end_selection(cx);
 652
 653//         view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 654//         view.update_selection(DisplayPoint::new(0, 3), 0, Point<Pixels>::zero(), cx);
 655//         view.end_selection(cx);
 656//         assert_eq!(
 657//             view.selections.display_ranges(cx),
 658//             [
 659//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 660//                 DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 661//             ]
 662//         );
 663//     });
 664
 665//     view.update(cx, |view, cx| {
 666//         view.cancel(&Cancel, cx);
 667//         assert_eq!(
 668//             view.selections.display_ranges(cx),
 669//             [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 670//         );
 671//     });
 672
 673//     view.update(cx, |view, cx| {
 674//         view.cancel(&Cancel, cx);
 675//         assert_eq!(
 676//             view.selections.display_ranges(cx),
 677//             [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 678//         );
 679//     });
 680// }
 681
 682// #[gpui::test]
 683// fn test_fold_action(cx: &mut TestAppContext) {
 684//     init_test(cx, |_| {});
 685
 686//     let view = cx
 687//         .add_window(|cx| {
 688//             let buffer = MultiBuffer::build_simple(
 689//                 &"
 690//                 impl Foo {
 691//                     // Hello!
 692
 693//                     fn a() {
 694//                         1
 695//                     }
 696
 697//                     fn b() {
 698//                         2
 699//                     }
 700
 701//                     fn c() {
 702//                         3
 703//                     }
 704//                 }
 705//             "
 706//                 .unindent(),
 707//                 cx,
 708//             );
 709//             build_editor(buffer.clone(), cx)
 710//         })
 711//         .root(cx);
 712
 713//     view.update(cx, |view, cx| {
 714//         view.change_selections(None, cx, |s| {
 715//             s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 716//         });
 717//         view.fold(&Fold, cx);
 718//         assert_eq!(
 719//             view.display_text(cx),
 720//             "
 721//                 impl Foo {
 722//                     // Hello!
 723
 724//                     fn a() {
 725//                         1
 726//                     }
 727
 728//                     fn b() {⋯
 729//                     }
 730
 731//                     fn c() {⋯
 732//                     }
 733//                 }
 734//             "
 735//             .unindent(),
 736//         );
 737
 738//         view.fold(&Fold, cx);
 739//         assert_eq!(
 740//             view.display_text(cx),
 741//             "
 742//                 impl Foo {⋯
 743//                 }
 744//             "
 745//             .unindent(),
 746//         );
 747
 748//         view.unfold_lines(&UnfoldLines, cx);
 749//         assert_eq!(
 750//             view.display_text(cx),
 751//             "
 752//                 impl Foo {
 753//                     // Hello!
 754
 755//                     fn a() {
 756//                         1
 757//                     }
 758
 759//                     fn b() {⋯
 760//                     }
 761
 762//                     fn c() {⋯
 763//                     }
 764//                 }
 765//             "
 766//             .unindent(),
 767//         );
 768
 769//         view.unfold_lines(&UnfoldLines, cx);
 770//         assert_eq!(view.display_text(cx), view.buffer.read(cx).read(cx).text());
 771//     });
 772// }
 773
 774// #[gpui::test]
 775// fn test_move_cursor(cx: &mut TestAppContext) {
 776//     init_test(cx, |_| {});
 777
 778//     let buffer = cx.update(|cx| MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx));
 779//     let view = cx
 780//         .add_window(|cx| build_editor(buffer.clone(), cx))
 781//         .root(cx);
 782
 783//     buffer.update(cx, |buffer, cx| {
 784//         buffer.edit(
 785//             vec![
 786//                 (Point::new(1, 0)..Point::new(1, 0), "\t"),
 787//                 (Point::new(1, 1)..Point::new(1, 1), "\t"),
 788//             ],
 789//             None,
 790//             cx,
 791//         );
 792//     });
 793//     view.update(cx, |view, cx| {
 794//         assert_eq!(
 795//             view.selections.display_ranges(cx),
 796//             &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 797//         );
 798
 799//         view.move_down(&MoveDown, cx);
 800//         assert_eq!(
 801//             view.selections.display_ranges(cx),
 802//             &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 803//         );
 804
 805//         view.move_right(&MoveRight, cx);
 806//         assert_eq!(
 807//             view.selections.display_ranges(cx),
 808//             &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 809//         );
 810
 811//         view.move_left(&MoveLeft, cx);
 812//         assert_eq!(
 813//             view.selections.display_ranges(cx),
 814//             &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 815//         );
 816
 817//         view.move_up(&MoveUp, cx);
 818//         assert_eq!(
 819//             view.selections.display_ranges(cx),
 820//             &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 821//         );
 822
 823//         view.move_to_end(&MoveToEnd, cx);
 824//         assert_eq!(
 825//             view.selections.display_ranges(cx),
 826//             &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 827//         );
 828
 829//         view.move_to_beginning(&MoveToBeginning, cx);
 830//         assert_eq!(
 831//             view.selections.display_ranges(cx),
 832//             &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 833//         );
 834
 835//         view.change_selections(None, cx, |s| {
 836//             s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 837//         });
 838//         view.select_to_beginning(&SelectToBeginning, cx);
 839//         assert_eq!(
 840//             view.selections.display_ranges(cx),
 841//             &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 842//         );
 843
 844//         view.select_to_end(&SelectToEnd, cx);
 845//         assert_eq!(
 846//             view.selections.display_ranges(cx),
 847//             &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 848//         );
 849//     });
 850// }
 851
 852// #[gpui::test]
 853// fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
 854//     init_test(cx, |_| {});
 855
 856//     let view = cx
 857//         .add_window(|cx| {
 858//             let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε", cx);
 859//             build_editor(buffer.clone(), cx)
 860//         })
 861//         .root(cx);
 862
 863//     assert_eq!('ⓐ'.len_utf8(), 3);
 864//     assert_eq!('α'.len_utf8(), 2);
 865
 866//     view.update(cx, |view, cx| {
 867//         view.fold_ranges(
 868//             vec![
 869//                 Point::new(0, 6)..Point::new(0, 12),
 870//                 Point::new(1, 2)..Point::new(1, 4),
 871//                 Point::new(2, 4)..Point::new(2, 8),
 872//             ],
 873//             true,
 874//             cx,
 875//         );
 876//         assert_eq!(view.display_text(cx), "ⓐⓑ⋯ⓔ\nab⋯e\nαβ⋯ε");
 877
 878//         view.move_right(&MoveRight, cx);
 879//         assert_eq!(
 880//             view.selections.display_ranges(cx),
 881//             &[empty_range(0, "ⓐ".len())]
 882//         );
 883//         view.move_right(&MoveRight, cx);
 884//         assert_eq!(
 885//             view.selections.display_ranges(cx),
 886//             &[empty_range(0, "ⓐⓑ".len())]
 887//         );
 888//         view.move_right(&MoveRight, cx);
 889//         assert_eq!(
 890//             view.selections.display_ranges(cx),
 891//             &[empty_range(0, "ⓐⓑ⋯".len())]
 892//         );
 893
 894//         view.move_down(&MoveDown, cx);
 895//         assert_eq!(
 896//             view.selections.display_ranges(cx),
 897//             &[empty_range(1, "ab⋯e".len())]
 898//         );
 899//         view.move_left(&MoveLeft, cx);
 900//         assert_eq!(
 901//             view.selections.display_ranges(cx),
 902//             &[empty_range(1, "ab⋯".len())]
 903//         );
 904//         view.move_left(&MoveLeft, cx);
 905//         assert_eq!(
 906//             view.selections.display_ranges(cx),
 907//             &[empty_range(1, "ab".len())]
 908//         );
 909//         view.move_left(&MoveLeft, cx);
 910//         assert_eq!(
 911//             view.selections.display_ranges(cx),
 912//             &[empty_range(1, "a".len())]
 913//         );
 914
 915//         view.move_down(&MoveDown, cx);
 916//         assert_eq!(
 917//             view.selections.display_ranges(cx),
 918//             &[empty_range(2, "α".len())]
 919//         );
 920//         view.move_right(&MoveRight, cx);
 921//         assert_eq!(
 922//             view.selections.display_ranges(cx),
 923//             &[empty_range(2, "αβ".len())]
 924//         );
 925//         view.move_right(&MoveRight, cx);
 926//         assert_eq!(
 927//             view.selections.display_ranges(cx),
 928//             &[empty_range(2, "αβ⋯".len())]
 929//         );
 930//         view.move_right(&MoveRight, cx);
 931//         assert_eq!(
 932//             view.selections.display_ranges(cx),
 933//             &[empty_range(2, "αβ⋯ε".len())]
 934//         );
 935
 936//         view.move_up(&MoveUp, cx);
 937//         assert_eq!(
 938//             view.selections.display_ranges(cx),
 939//             &[empty_range(1, "ab⋯e".len())]
 940//         );
 941//         view.move_down(&MoveDown, cx);
 942//         assert_eq!(
 943//             view.selections.display_ranges(cx),
 944//             &[empty_range(2, "αβ⋯ε".len())]
 945//         );
 946//         view.move_up(&MoveUp, cx);
 947//         assert_eq!(
 948//             view.selections.display_ranges(cx),
 949//             &[empty_range(1, "ab⋯e".len())]
 950//         );
 951
 952//         view.move_up(&MoveUp, cx);
 953//         assert_eq!(
 954//             view.selections.display_ranges(cx),
 955//             &[empty_range(0, "ⓐⓑ".len())]
 956//         );
 957//         view.move_left(&MoveLeft, cx);
 958//         assert_eq!(
 959//             view.selections.display_ranges(cx),
 960//             &[empty_range(0, "ⓐ".len())]
 961//         );
 962//         view.move_left(&MoveLeft, cx);
 963//         assert_eq!(
 964//             view.selections.display_ranges(cx),
 965//             &[empty_range(0, "".len())]
 966//         );
 967//     });
 968// }
 969
 970// #[gpui::test]
 971// fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) {
 972//     init_test(cx, |_| {});
 973
 974//     let view = cx
 975//         .add_window(|cx| {
 976//             let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 977//             build_editor(buffer.clone(), cx)
 978//         })
 979//         .root(cx);
 980//     view.update(cx, |view, cx| {
 981//         view.change_selections(None, cx, |s| {
 982//             s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 983//         });
 984//         view.move_down(&MoveDown, cx);
 985//         assert_eq!(
 986//             view.selections.display_ranges(cx),
 987//             &[empty_range(1, "abcd".len())]
 988//         );
 989
 990//         view.move_down(&MoveDown, cx);
 991//         assert_eq!(
 992//             view.selections.display_ranges(cx),
 993//             &[empty_range(2, "αβγ".len())]
 994//         );
 995
 996//         view.move_down(&MoveDown, cx);
 997//         assert_eq!(
 998//             view.selections.display_ranges(cx),
 999//             &[empty_range(3, "abcd".len())]
1000//         );
1001
1002//         view.move_down(&MoveDown, cx);
1003//         assert_eq!(
1004//             view.selections.display_ranges(cx),
1005//             &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
1006//         );
1007
1008//         view.move_up(&MoveUp, cx);
1009//         assert_eq!(
1010//             view.selections.display_ranges(cx),
1011//             &[empty_range(3, "abcd".len())]
1012//         );
1013
1014//         view.move_up(&MoveUp, cx);
1015//         assert_eq!(
1016//             view.selections.display_ranges(cx),
1017//             &[empty_range(2, "αβγ".len())]
1018//         );
1019//     });
1020// }
1021
1022// #[gpui::test]
1023// fn test_beginning_end_of_line(cx: &mut TestAppContext) {
1024//     init_test(cx, |_| {});
1025
1026//     let view = cx
1027//         .add_window(|cx| {
1028//             let buffer = MultiBuffer::build_simple("abc\n  def", cx);
1029//             build_editor(buffer, cx)
1030//         })
1031//         .root(cx);
1032//     view.update(cx, |view, cx| {
1033//         view.change_selections(None, cx, |s| {
1034//             s.select_display_ranges([
1035//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
1036//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
1037//             ]);
1038//         });
1039//     });
1040
1041//     view.update(cx, |view, cx| {
1042//         view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
1043//         assert_eq!(
1044//             view.selections.display_ranges(cx),
1045//             &[
1046//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
1047//                 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
1048//             ]
1049//         );
1050//     });
1051
1052//     view.update(cx, |view, cx| {
1053//         view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
1054//         assert_eq!(
1055//             view.selections.display_ranges(cx),
1056//             &[
1057//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
1058//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
1059//             ]
1060//         );
1061//     });
1062
1063//     view.update(cx, |view, cx| {
1064//         view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
1065//         assert_eq!(
1066//             view.selections.display_ranges(cx),
1067//             &[
1068//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
1069//                 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
1070//             ]
1071//         );
1072//     });
1073
1074//     view.update(cx, |view, cx| {
1075//         view.move_to_end_of_line(&MoveToEndOfLine, cx);
1076//         assert_eq!(
1077//             view.selections.display_ranges(cx),
1078//             &[
1079//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
1080//                 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
1081//             ]
1082//         );
1083//     });
1084
1085//     // Moving to the end of line again is a no-op.
1086//     view.update(cx, |view, cx| {
1087//         view.move_to_end_of_line(&MoveToEndOfLine, cx);
1088//         assert_eq!(
1089//             view.selections.display_ranges(cx),
1090//             &[
1091//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
1092//                 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
1093//             ]
1094//         );
1095//     });
1096
1097//     view.update(cx, |view, cx| {
1098//         view.move_left(&MoveLeft, cx);
1099//         view.select_to_beginning_of_line(
1100//             &SelectToBeginningOfLine {
1101//                 stop_at_soft_wraps: true,
1102//             },
1103//             cx,
1104//         );
1105//         assert_eq!(
1106//             view.selections.display_ranges(cx),
1107//             &[
1108//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
1109//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
1110//             ]
1111//         );
1112//     });
1113
1114//     view.update(cx, |view, cx| {
1115//         view.select_to_beginning_of_line(
1116//             &SelectToBeginningOfLine {
1117//                 stop_at_soft_wraps: true,
1118//             },
1119//             cx,
1120//         );
1121//         assert_eq!(
1122//             view.selections.display_ranges(cx),
1123//             &[
1124//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
1125//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
1126//             ]
1127//         );
1128//     });
1129
1130//     view.update(cx, |view, cx| {
1131//         view.select_to_beginning_of_line(
1132//             &SelectToBeginningOfLine {
1133//                 stop_at_soft_wraps: true,
1134//             },
1135//             cx,
1136//         );
1137//         assert_eq!(
1138//             view.selections.display_ranges(cx),
1139//             &[
1140//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
1141//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
1142//             ]
1143//         );
1144//     });
1145
1146//     view.update(cx, |view, cx| {
1147//         view.select_to_end_of_line(
1148//             &SelectToEndOfLine {
1149//                 stop_at_soft_wraps: true,
1150//             },
1151//             cx,
1152//         );
1153//         assert_eq!(
1154//             view.selections.display_ranges(cx),
1155//             &[
1156//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
1157//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
1158//             ]
1159//         );
1160//     });
1161
1162//     view.update(cx, |view, cx| {
1163//         view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
1164//         assert_eq!(view.display_text(cx), "ab\n  de");
1165//         assert_eq!(
1166//             view.selections.display_ranges(cx),
1167//             &[
1168//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
1169//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
1170//             ]
1171//         );
1172//     });
1173
1174//     view.update(cx, |view, cx| {
1175//         view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
1176//         assert_eq!(view.display_text(cx), "\n");
1177//         assert_eq!(
1178//             view.selections.display_ranges(cx),
1179//             &[
1180//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
1181//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
1182//             ]
1183//         );
1184//     });
1185// }
1186
1187// #[gpui::test]
1188// fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
1189//     init_test(cx, |_| {});
1190
1191//     let view = cx
1192//         .add_window(|cx| {
1193//             let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
1194//             build_editor(buffer, cx)
1195//         })
1196//         .root(cx);
1197//     view.update(cx, |view, cx| {
1198//         view.change_selections(None, cx, |s| {
1199//             s.select_display_ranges([
1200//                 DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
1201//                 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
1202//             ])
1203//         });
1204
1205//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1206//         assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
1207
1208//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1209//         assert_selection_ranges("use stdˇ::str::{foo, bar}\n\n  ˇ{baz.qux()}", view, cx);
1210
1211//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1212//         assert_selection_ranges("use ˇstd::str::{foo, bar}\n\nˇ  {baz.qux()}", view, cx);
1213
1214//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1215//         assert_selection_ranges("ˇuse std::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
1216
1217//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1218//         assert_selection_ranges("ˇuse std::str::{foo, barˇ}\n\n  {baz.qux()}", view, cx);
1219
1220//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1221//         assert_selection_ranges("useˇ std::str::{foo, bar}ˇ\n\n  {baz.qux()}", view, cx);
1222
1223//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1224//         assert_selection_ranges("use stdˇ::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
1225
1226//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1227//         assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
1228
1229//         view.move_right(&MoveRight, cx);
1230//         view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
1231//         assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
1232
1233//         view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
1234//         assert_selection_ranges("use std«ˇ::s»tr::{foo, bar}\n\n  «ˇ{b»az.qux()}", view, cx);
1235
1236//         view.select_to_next_word_end(&SelectToNextWordEnd, cx);
1237//         assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
1238//     });
1239// }
1240
1241// #[gpui::test]
1242// fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
1243//     init_test(cx, |_| {});
1244
1245//     let view = cx
1246//         .add_window(|cx| {
1247//             let buffer =
1248//                 MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
1249//             build_editor(buffer, cx)
1250//         })
1251//         .root(cx);
1252
1253//     view.update(cx, |view, cx| {
1254//         view.set_wrap_width(Some(140.), cx);
1255//         assert_eq!(
1256//             view.display_text(cx),
1257//             "use one::{\n    two::three::\n    four::five\n};"
1258//         );
1259
1260//         view.change_selections(None, cx, |s| {
1261//             s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
1262//         });
1263
1264//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1265//         assert_eq!(
1266//             view.selections.display_ranges(cx),
1267//             &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
1268//         );
1269
1270//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1271//         assert_eq!(
1272//             view.selections.display_ranges(cx),
1273//             &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
1274//         );
1275
1276//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1277//         assert_eq!(
1278//             view.selections.display_ranges(cx),
1279//             &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
1280//         );
1281
1282//         view.move_to_next_word_end(&MoveToNextWordEnd, cx);
1283//         assert_eq!(
1284//             view.selections.display_ranges(cx),
1285//             &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
1286//         );
1287
1288//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1289//         assert_eq!(
1290//             view.selections.display_ranges(cx),
1291//             &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
1292//         );
1293
1294//         view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
1295//         assert_eq!(
1296//             view.selections.display_ranges(cx),
1297//             &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
1298//         );
1299//     });
1300// }
1301
1302// #[gpui::test]
1303// async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) {
1304//     init_test(cx, |_| {});
1305//     let mut cx = EditorTestContext::new(cx).await;
1306
1307//     let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache()));
1308//     let window = cx.window;
1309//     window.simulate_resize(vec2f(100., 4. * line_height), &mut cx);
1310
1311//     cx.set_state(
1312//         &r#"ˇone
1313//         two
1314
1315//         three
1316//         fourˇ
1317//         five
1318
1319//         six"#
1320//             .unindent(),
1321//     );
1322
1323//     cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
1324//     cx.assert_editor_state(
1325//         &r#"one
1326//         two
1327//         ˇ
1328//         three
1329//         four
1330//         five
1331//         ˇ
1332//         six"#
1333//             .unindent(),
1334//     );
1335
1336//     cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
1337//     cx.assert_editor_state(
1338//         &r#"one
1339//         two
1340
1341//         three
1342//         four
1343//         five
1344//         ˇ
1345//         sixˇ"#
1346//             .unindent(),
1347//     );
1348
1349//     cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx));
1350//     cx.assert_editor_state(
1351//         &r#"one
1352//         two
1353
1354//         three
1355//         four
1356//         five
1357
1358//         sixˇ"#
1359//             .unindent(),
1360//     );
1361
1362//     cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
1363//     cx.assert_editor_state(
1364//         &r#"one
1365//         two
1366
1367//         three
1368//         four
1369//         five
1370//         ˇ
1371//         six"#
1372//             .unindent(),
1373//     );
1374
1375//     cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
1376//     cx.assert_editor_state(
1377//         &r#"one
1378//         two
1379//         ˇ
1380//         three
1381//         four
1382//         five
1383
1384//         six"#
1385//             .unindent(),
1386//     );
1387
1388//     cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx));
1389//     cx.assert_editor_state(
1390//         &r#"ˇone
1391//         two
1392
1393//         three
1394//         four
1395//         five
1396
1397//         six"#
1398//             .unindent(),
1399//     );
1400// }
1401
1402// #[gpui::test]
1403// async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) {
1404//     init_test(cx, |_| {});
1405//     let mut cx = EditorTestContext::new(cx).await;
1406//     let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache()));
1407//     let window = cx.window;
1408//     window.simulate_resize(vec2f(1000., 4. * line_height + 0.5), &mut cx);
1409
1410//     cx.set_state(
1411//         &r#"ˇone
1412//         two
1413//         three
1414//         four
1415//         five
1416//         six
1417//         seven
1418//         eight
1419//         nine
1420//         ten
1421//         "#,
1422//     );
1423
1424//     cx.update_editor(|editor, cx| {
1425//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.));
1426//         editor.scroll_screen(&ScrollAmount::Page(1.), cx);
1427//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.));
1428//         editor.scroll_screen(&ScrollAmount::Page(1.), cx);
1429//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 6.));
1430//         editor.scroll_screen(&ScrollAmount::Page(-1.), cx);
1431//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.));
1432
1433//         editor.scroll_screen(&ScrollAmount::Page(-0.5), cx);
1434//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 1.));
1435//         editor.scroll_screen(&ScrollAmount::Page(0.5), cx);
1436//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.));
1437//     });
1438// }
1439
1440// #[gpui::test]
1441// async fn test_autoscroll(cx: &mut gpui::TestAppContext) {
1442//     init_test(cx, |_| {});
1443//     let mut cx = EditorTestContext::new(cx).await;
1444
1445//     let line_height = cx.update_editor(|editor, cx| {
1446//         editor.set_vertical_scroll_margin(2, cx);
1447//         editor.style(cx).text.line_height(cx.font_cache())
1448//     });
1449
1450//     let window = cx.window;
1451//     window.simulate_resize(vec2f(1000., 6.0 * line_height), &mut cx);
1452
1453//     cx.set_state(
1454//         &r#"ˇone
1455//             two
1456//             three
1457//             four
1458//             five
1459//             six
1460//             seven
1461//             eight
1462//             nine
1463//             ten
1464//         "#,
1465//     );
1466//     cx.update_editor(|editor, cx| {
1467//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.0));
1468//     });
1469
1470//     // Add a cursor below the visible area. Since both cursors cannot fit
1471//     // on screen, the editor autoscrolls to reveal the newest cursor, and
1472//     // allows the vertical scroll margin below that cursor.
1473//     cx.update_editor(|editor, cx| {
1474//         editor.change_selections(Some(Autoscroll::fit()), cx, |selections| {
1475//             selections.select_ranges([
1476//                 Point::new(0, 0)..Point::new(0, 0),
1477//                 Point::new(6, 0)..Point::new(6, 0),
1478//             ]);
1479//         })
1480//     });
1481//     cx.update_editor(|editor, cx| {
1482//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.0));
1483//     });
1484
1485//     // Move down. The editor cursor scrolls down to track the newest cursor.
1486//     cx.update_editor(|editor, cx| {
1487//         editor.move_down(&Default::default(), cx);
1488//     });
1489//     cx.update_editor(|editor, cx| {
1490//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 4.0));
1491//     });
1492
1493//     // Add a cursor above the visible area. Since both cursors fit on screen,
1494//     // the editor scrolls to show both.
1495//     cx.update_editor(|editor, cx| {
1496//         editor.change_selections(Some(Autoscroll::fit()), cx, |selections| {
1497//             selections.select_ranges([
1498//                 Point::new(1, 0)..Point::new(1, 0),
1499//                 Point::new(6, 0)..Point::new(6, 0),
1500//             ]);
1501//         })
1502//     });
1503//     cx.update_editor(|editor, cx| {
1504//         assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 1.0));
1505//     });
1506// }
1507
1508// #[gpui::test]
1509// async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) {
1510//     init_test(cx, |_| {});
1511//     let mut cx = EditorTestContext::new(cx).await;
1512
1513//     let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache()));
1514//     let window = cx.window;
1515//     window.simulate_resize(vec2f(100., 4. * line_height), &mut cx);
1516
1517//     cx.set_state(
1518//         &r#"
1519//         ˇone
1520//         two
1521//         threeˇ
1522//         four
1523//         five
1524//         six
1525//         seven
1526//         eight
1527//         nine
1528//         ten
1529//         "#
1530//         .unindent(),
1531//     );
1532
1533//     cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx));
1534//     cx.assert_editor_state(
1535//         &r#"
1536//         one
1537//         two
1538//         three
1539//         ˇfour
1540//         five
1541//         sixˇ
1542//         seven
1543//         eight
1544//         nine
1545//         ten
1546//         "#
1547//         .unindent(),
1548//     );
1549
1550//     cx.update_editor(|editor, cx| editor.move_page_down(&MovePageDown::default(), cx));
1551//     cx.assert_editor_state(
1552//         &r#"
1553//         one
1554//         two
1555//         three
1556//         four
1557//         five
1558//         six
1559//         ˇseven
1560//         eight
1561//         nineˇ
1562//         ten
1563//         "#
1564//         .unindent(),
1565//     );
1566
1567//     cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx));
1568//     cx.assert_editor_state(
1569//         &r#"
1570//         one
1571//         two
1572//         three
1573//         ˇfour
1574//         five
1575//         sixˇ
1576//         seven
1577//         eight
1578//         nine
1579//         ten
1580//         "#
1581//         .unindent(),
1582//     );
1583
1584//     cx.update_editor(|editor, cx| editor.move_page_up(&MovePageUp::default(), cx));
1585//     cx.assert_editor_state(
1586//         &r#"
1587//         ˇone
1588//         two
1589//         threeˇ
1590//         four
1591//         five
1592//         six
1593//         seven
1594//         eight
1595//         nine
1596//         ten
1597//         "#
1598//         .unindent(),
1599//     );
1600
1601//     // Test select collapsing
1602//     cx.update_editor(|editor, cx| {
1603//         editor.move_page_down(&MovePageDown::default(), cx);
1604//         editor.move_page_down(&MovePageDown::default(), cx);
1605//         editor.move_page_down(&MovePageDown::default(), cx);
1606//     });
1607//     cx.assert_editor_state(
1608//         &r#"
1609//         one
1610//         two
1611//         three
1612//         four
1613//         five
1614//         six
1615//         seven
1616//         eight
1617//         nine
1618//         ˇten
1619//         ˇ"#
1620//         .unindent(),
1621//     );
1622// }
1623
1624// #[gpui::test]
1625// async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
1626//     init_test(cx, |_| {});
1627//     let mut cx = EditorTestContext::new(cx).await;
1628//     cx.set_state("one «two threeˇ» four");
1629//     cx.update_editor(|editor, cx| {
1630//         editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
1631//         assert_eq!(editor.text(cx), " four");
1632//     });
1633// }
1634
1635// #[gpui::test]
1636// fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
1637//     init_test(cx, |_| {});
1638
1639//     let view = cx
1640//         .add_window(|cx| {
1641//             let buffer = MultiBuffer::build_simple("one two three four", cx);
1642//             build_editor(buffer.clone(), cx)
1643//         })
1644//         .root(cx);
1645
1646//     view.update(cx, |view, cx| {
1647//         view.change_selections(None, cx, |s| {
1648//             s.select_display_ranges([
1649//                 // an empty selection - the preceding word fragment is deleted
1650//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
1651//                 // characters selected - they are deleted
1652//                 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
1653//             ])
1654//         });
1655//         view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
1656//         assert_eq!(view.buffer.read(cx).read(cx).text(), "e two te four");
1657//     });
1658
1659//     view.update(cx, |view, cx| {
1660//         view.change_selections(None, cx, |s| {
1661//             s.select_display_ranges([
1662//                 // an empty selection - the following word fragment is deleted
1663//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
1664//                 // characters selected - they are deleted
1665//                 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
1666//             ])
1667//         });
1668//         view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
1669//         assert_eq!(view.buffer.read(cx).read(cx).text(), "e t te our");
1670//     });
1671// }
1672
1673// #[gpui::test]
1674// fn test_newline(cx: &mut TestAppContext) {
1675//     init_test(cx, |_| {});
1676
1677//     let view = cx
1678//         .add_window(|cx| {
1679//             let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
1680//             build_editor(buffer.clone(), cx)
1681//         })
1682//         .root(cx);
1683
1684//     view.update(cx, |view, cx| {
1685//         view.change_selections(None, cx, |s| {
1686//             s.select_display_ranges([
1687//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
1688//                 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
1689//                 DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
1690//             ])
1691//         });
1692
1693//         view.newline(&Newline, cx);
1694//         assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
1695//     });
1696// }
1697
1698// #[gpui::test]
1699// fn test_newline_with_old_selections(cx: &mut TestAppContext) {
1700//     init_test(cx, |_| {});
1701
1702//     let editor = cx
1703//         .add_window(|cx| {
1704//             let buffer = MultiBuffer::build_simple(
1705//                 "
1706//                 a
1707//                 b(
1708//                     X
1709//                 )
1710//                 c(
1711//                     X
1712//                 )
1713//             "
1714//                 .unindent()
1715//                 .as_str(),
1716//                 cx,
1717//             );
1718//             let mut editor = build_editor(buffer.clone(), cx);
1719//             editor.change_selections(None, cx, |s| {
1720//                 s.select_ranges([
1721//                     Point::new(2, 4)..Point::new(2, 5),
1722//                     Point::new(5, 4)..Point::new(5, 5),
1723//                 ])
1724//             });
1725//             editor
1726//         })
1727//         .root(cx);
1728
1729//     editor.update(cx, |editor, cx| {
1730//         // Edit the buffer directly, deleting ranges surrounding the editor's selections
1731//         editor.buffer.update(cx, |buffer, cx| {
1732//             buffer.edit(
1733//                 [
1734//                     (Point::new(1, 2)..Point::new(3, 0), ""),
1735//                     (Point::new(4, 2)..Point::new(6, 0), ""),
1736//                 ],
1737//                 None,
1738//                 cx,
1739//             );
1740//             assert_eq!(
1741//                 buffer.read(cx).text(),
1742//                 "
1743//                     a
1744//                     b()
1745//                     c()
1746//                 "
1747//                 .unindent()
1748//             );
1749//         });
1750//         assert_eq!(
1751//             editor.selections.ranges(cx),
1752//             &[
1753//                 Point::new(1, 2)..Point::new(1, 2),
1754//                 Point::new(2, 2)..Point::new(2, 2),
1755//             ],
1756//         );
1757
1758//         editor.newline(&Newline, cx);
1759//         assert_eq!(
1760//             editor.text(cx),
1761//             "
1762//                 a
1763//                 b(
1764//                 )
1765//                 c(
1766//                 )
1767//             "
1768//             .unindent()
1769//         );
1770
1771//         // The selections are moved after the inserted newlines
1772//         assert_eq!(
1773//             editor.selections.ranges(cx),
1774//             &[
1775//                 Point::new(2, 0)..Point::new(2, 0),
1776//                 Point::new(4, 0)..Point::new(4, 0),
1777//             ],
1778//         );
1779//     });
1780// }
1781
1782// #[gpui::test]
1783// async fn test_newline_above(cx: &mut gpui::TestAppContext) {
1784//     init_test(cx, |settings| {
1785//         settings.defaults.tab_size = NonZeroU32::new(4)
1786//     });
1787
1788//     let language = Arc::new(
1789//         Language::new(
1790//             LanguageConfig::default(),
1791//             Some(tree_sitter_rust::language()),
1792//         )
1793//         .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
1794//         .unwrap(),
1795//     );
1796
1797//     let mut cx = EditorTestContext::new(cx).await;
1798//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
1799//     cx.set_state(indoc! {"
1800//         const a: ˇA = (
1801//             (ˇ
1802//                 «const_functionˇ»(ˇ),
1803//                 so«mˇ»et«hˇ»ing_ˇelse,ˇ
1804//             )ˇ
1805//         ˇ);ˇ
1806//     "});
1807
1808//     cx.update_editor(|e, cx| e.newline_above(&NewlineAbove, cx));
1809//     cx.assert_editor_state(indoc! {"
1810//         ˇ
1811//         const a: A = (
1812//             ˇ
1813//             (
1814//                 ˇ
1815//                 ˇ
1816//                 const_function(),
1817//                 ˇ
1818//                 ˇ
1819//                 ˇ
1820//                 ˇ
1821//                 something_else,
1822//                 ˇ
1823//             )
1824//             ˇ
1825//             ˇ
1826//         );
1827//     "});
1828// }
1829
1830// #[gpui::test]
1831// async fn test_newline_below(cx: &mut gpui::TestAppContext) {
1832//     init_test(cx, |settings| {
1833//         settings.defaults.tab_size = NonZeroU32::new(4)
1834//     });
1835
1836//     let language = Arc::new(
1837//         Language::new(
1838//             LanguageConfig::default(),
1839//             Some(tree_sitter_rust::language()),
1840//         )
1841//         .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
1842//         .unwrap(),
1843//     );
1844
1845//     let mut cx = EditorTestContext::new(cx).await;
1846//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
1847//     cx.set_state(indoc! {"
1848//         const a: ˇA = (
1849//             (ˇ
1850//                 «const_functionˇ»(ˇ),
1851//                 so«mˇ»et«hˇ»ing_ˇelse,ˇ
1852//             )ˇ
1853//         ˇ);ˇ
1854//     "});
1855
1856//     cx.update_editor(|e, cx| e.newline_below(&NewlineBelow, cx));
1857//     cx.assert_editor_state(indoc! {"
1858//         const a: A = (
1859//             ˇ
1860//             (
1861//                 ˇ
1862//                 const_function(),
1863//                 ˇ
1864//                 ˇ
1865//                 something_else,
1866//                 ˇ
1867//                 ˇ
1868//                 ˇ
1869//                 ˇ
1870//             )
1871//             ˇ
1872//         );
1873//         ˇ
1874//         ˇ
1875//     "});
1876// }
1877
1878// #[gpui::test]
1879// async fn test_newline_comments(cx: &mut gpui::TestAppContext) {
1880//     init_test(cx, |settings| {
1881//         settings.defaults.tab_size = NonZeroU32::new(4)
1882//     });
1883
1884//     let language = Arc::new(Language::new(
1885//         LanguageConfig {
1886//             line_comment: Some("//".into()),
1887//             ..LanguageConfig::default()
1888//         },
1889//         None,
1890//     ));
1891//     {
1892//         let mut cx = EditorTestContext::new(cx).await;
1893//         cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
1894//         cx.set_state(indoc! {"
1895//         // Fooˇ
1896//     "});
1897
1898//         cx.update_editor(|e, cx| e.newline(&Newline, cx));
1899//         cx.assert_editor_state(indoc! {"
1900//         // Foo
1901//         //ˇ
1902//     "});
1903//         // Ensure that if cursor is before the comment start, we do not actually insert a comment prefix.
1904//         cx.set_state(indoc! {"
1905//         ˇ// Foo
1906//     "});
1907//         cx.update_editor(|e, cx| e.newline(&Newline, cx));
1908//         cx.assert_editor_state(indoc! {"
1909
1910//         ˇ// Foo
1911//     "});
1912//     }
1913//     // Ensure that comment continuations can be disabled.
1914//     update_test_language_settings(cx, |settings| {
1915//         settings.defaults.extend_comment_on_newline = Some(false);
1916//     });
1917//     let mut cx = EditorTestContext::new(cx).await;
1918//     cx.set_state(indoc! {"
1919//         // Fooˇ
1920//     "});
1921//     cx.update_editor(|e, cx| e.newline(&Newline, cx));
1922//     cx.assert_editor_state(indoc! {"
1923//         // Foo
1924//         ˇ
1925//     "});
1926// }
1927
1928// #[gpui::test]
1929// fn test_insert_with_old_selections(cx: &mut TestAppContext) {
1930//     init_test(cx, |_| {});
1931
1932//     let editor = cx
1933//         .add_window(|cx| {
1934//             let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
1935//             let mut editor = build_editor(buffer.clone(), cx);
1936//             editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
1937//             editor
1938//         })
1939//         .root(cx);
1940
1941//     editor.update(cx, |editor, cx| {
1942//         // Edit the buffer directly, deleting ranges surrounding the editor's selections
1943//         editor.buffer.update(cx, |buffer, cx| {
1944//             buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
1945//             assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
1946//         });
1947//         assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
1948
1949//         editor.insert("Z", cx);
1950//         assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
1951
1952//         // The selections are moved after the inserted characters
1953//         assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
1954//     });
1955// }
1956
1957// #[gpui::test]
1958// async fn test_tab(cx: &mut gpui::TestAppContext) {
1959//     init_test(cx, |settings| {
1960//         settings.defaults.tab_size = NonZeroU32::new(3)
1961//     });
1962
1963//     let mut cx = EditorTestContext::new(cx).await;
1964//     cx.set_state(indoc! {"
1965//         ˇabˇc
1966//         ˇ🏀ˇ🏀ˇefg
1967//         dˇ
1968//     "});
1969//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
1970//     cx.assert_editor_state(indoc! {"
1971//            ˇab ˇc
1972//            ˇ🏀  ˇ🏀  ˇefg
1973//         d  ˇ
1974//     "});
1975
1976//     cx.set_state(indoc! {"
1977//         a
1978//         «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
1979//     "});
1980//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
1981//     cx.assert_editor_state(indoc! {"
1982//         a
1983//            «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
1984//     "});
1985// }
1986
1987// #[gpui::test]
1988// async fn test_tab_in_leading_whitespace_auto_indents_lines(cx: &mut gpui::TestAppContext) {
1989//     init_test(cx, |_| {});
1990
1991//     let mut cx = EditorTestContext::new(cx).await;
1992//     let language = Arc::new(
1993//         Language::new(
1994//             LanguageConfig::default(),
1995//             Some(tree_sitter_rust::language()),
1996//         )
1997//         .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
1998//         .unwrap(),
1999//     );
2000//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
2001
2002//     // cursors that are already at the suggested indent level insert
2003//     // a soft tab. cursors that are to the left of the suggested indent
2004//     // auto-indent their line.
2005//     cx.set_state(indoc! {"
2006//         ˇ
2007//         const a: B = (
2008//             c(
2009//                 d(
2010//         ˇ
2011//                 )
2012//         ˇ
2013//         ˇ    )
2014//         );
2015//     "});
2016//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2017//     cx.assert_editor_state(indoc! {"
2018//             ˇ
2019//         const a: B = (
2020//             c(
2021//                 d(
2022//                     ˇ
2023//                 )
2024//                 ˇ
2025//             ˇ)
2026//         );
2027//     "});
2028
2029//     // handle auto-indent when there are multiple cursors on the same line
2030//     cx.set_state(indoc! {"
2031//         const a: B = (
2032//             c(
2033//         ˇ    ˇ
2034//         ˇ    )
2035//         );
2036//     "});
2037//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2038//     cx.assert_editor_state(indoc! {"
2039//         const a: B = (
2040//             c(
2041//                 ˇ
2042//             ˇ)
2043//         );
2044//     "});
2045// }
2046
2047// #[gpui::test]
2048// async fn test_tab_with_mixed_whitespace(cx: &mut gpui::TestAppContext) {
2049//     init_test(cx, |settings| {
2050//         settings.defaults.tab_size = NonZeroU32::new(4)
2051//     });
2052
2053//     let language = Arc::new(
2054//         Language::new(
2055//             LanguageConfig::default(),
2056//             Some(tree_sitter_rust::language()),
2057//         )
2058//         .with_indents_query(r#"(_ "{" "}" @end) @indent"#)
2059//         .unwrap(),
2060//     );
2061
2062//     let mut cx = EditorTestContext::new(cx).await;
2063//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
2064//     cx.set_state(indoc! {"
2065//         fn a() {
2066//             if b {
2067//         \t ˇc
2068//             }
2069//         }
2070//     "});
2071
2072//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2073//     cx.assert_editor_state(indoc! {"
2074//         fn a() {
2075//             if b {
2076//                 ˇc
2077//             }
2078//         }
2079//     "});
2080// }
2081
2082// #[gpui::test]
2083// async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
2084//     init_test(cx, |settings| {
2085//         settings.defaults.tab_size = NonZeroU32::new(4);
2086//     });
2087
2088//     let mut cx = EditorTestContext::new(cx).await;
2089
2090//     cx.set_state(indoc! {"
2091//           «oneˇ» «twoˇ»
2092//         three
2093//          four
2094//     "});
2095//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2096//     cx.assert_editor_state(indoc! {"
2097//             «oneˇ» «twoˇ»
2098//         three
2099//          four
2100//     "});
2101
2102//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2103//     cx.assert_editor_state(indoc! {"
2104//         «oneˇ» «twoˇ»
2105//         three
2106//          four
2107//     "});
2108
2109//     // select across line ending
2110//     cx.set_state(indoc! {"
2111//         one two
2112//         t«hree
2113//         ˇ» four
2114//     "});
2115//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2116//     cx.assert_editor_state(indoc! {"
2117//         one two
2118//             t«hree
2119//         ˇ» four
2120//     "});
2121
2122//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2123//     cx.assert_editor_state(indoc! {"
2124//         one two
2125//         t«hree
2126//         ˇ» four
2127//     "});
2128
2129//     // Ensure that indenting/outdenting works when the cursor is at column 0.
2130//     cx.set_state(indoc! {"
2131//         one two
2132//         ˇthree
2133//             four
2134//     "});
2135//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2136//     cx.assert_editor_state(indoc! {"
2137//         one two
2138//             ˇthree
2139//             four
2140//     "});
2141
2142//     cx.set_state(indoc! {"
2143//         one two
2144//         ˇ    three
2145//             four
2146//     "});
2147//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2148//     cx.assert_editor_state(indoc! {"
2149//         one two
2150//         ˇthree
2151//             four
2152//     "});
2153// }
2154
2155// #[gpui::test]
2156// async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
2157//     init_test(cx, |settings| {
2158//         settings.defaults.hard_tabs = Some(true);
2159//     });
2160
2161//     let mut cx = EditorTestContext::new(cx).await;
2162
2163//     // select two ranges on one line
2164//     cx.set_state(indoc! {"
2165//         «oneˇ» «twoˇ»
2166//         three
2167//         four
2168//     "});
2169//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2170//     cx.assert_editor_state(indoc! {"
2171//         \t«oneˇ» «twoˇ»
2172//         three
2173//         four
2174//     "});
2175//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2176//     cx.assert_editor_state(indoc! {"
2177//         \t\t«oneˇ» «twoˇ»
2178//         three
2179//         four
2180//     "});
2181//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2182//     cx.assert_editor_state(indoc! {"
2183//         \t«oneˇ» «twoˇ»
2184//         three
2185//         four
2186//     "});
2187//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2188//     cx.assert_editor_state(indoc! {"
2189//         «oneˇ» «twoˇ»
2190//         three
2191//         four
2192//     "});
2193
2194//     // select across a line ending
2195//     cx.set_state(indoc! {"
2196//         one two
2197//         t«hree
2198//         ˇ»four
2199//     "});
2200//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2201//     cx.assert_editor_state(indoc! {"
2202//         one two
2203//         \tt«hree
2204//         ˇ»four
2205//     "});
2206//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2207//     cx.assert_editor_state(indoc! {"
2208//         one two
2209//         \t\tt«hree
2210//         ˇ»four
2211//     "});
2212//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2213//     cx.assert_editor_state(indoc! {"
2214//         one two
2215//         \tt«hree
2216//         ˇ»four
2217//     "});
2218//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2219//     cx.assert_editor_state(indoc! {"
2220//         one two
2221//         t«hree
2222//         ˇ»four
2223//     "});
2224
2225//     // Ensure that indenting/outdenting works when the cursor is at column 0.
2226//     cx.set_state(indoc! {"
2227//         one two
2228//         ˇthree
2229//         four
2230//     "});
2231//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2232//     cx.assert_editor_state(indoc! {"
2233//         one two
2234//         ˇthree
2235//         four
2236//     "});
2237//     cx.update_editor(|e, cx| e.tab(&Tab, cx));
2238//     cx.assert_editor_state(indoc! {"
2239//         one two
2240//         \tˇthree
2241//         four
2242//     "});
2243//     cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
2244//     cx.assert_editor_state(indoc! {"
2245//         one two
2246//         ˇthree
2247//         four
2248//     "});
2249// }
2250
2251// #[gpui::test]
2252// fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) {
2253//     init_test(cx, |settings| {
2254//         settings.languages.extend([
2255//             (
2256//                 "TOML".into(),
2257//                 LanguageSettingsContent {
2258//                     tab_size: NonZeroU32::new(2),
2259//                     ..Default::default()
2260//                 },
2261//             ),
2262//             (
2263//                 "Rust".into(),
2264//                 LanguageSettingsContent {
2265//                     tab_size: NonZeroU32::new(4),
2266//                     ..Default::default()
2267//                 },
2268//             ),
2269//         ]);
2270//     });
2271
2272//     let toml_language = Arc::new(Language::new(
2273//         LanguageConfig {
2274//             name: "TOML".into(),
2275//             ..Default::default()
2276//         },
2277//         None,
2278//     ));
2279//     let rust_language = Arc::new(Language::new(
2280//         LanguageConfig {
2281//             name: "Rust".into(),
2282//             ..Default::default()
2283//         },
2284//         None,
2285//     ));
2286
2287//     let toml_buffer = cx.add_model(|cx| {
2288//         Buffer::new(0, cx.model_id() as u64, "a = 1\nb = 2\n").with_language(toml_language, cx)
2289//     });
2290//     let rust_buffer = cx.add_model(|cx| {
2291//         Buffer::new(0, cx.model_id() as u64, "const c: usize = 3;\n")
2292//             .with_language(rust_language, cx)
2293//     });
2294//     let multibuffer = cx.add_model(|cx| {
2295//         let mut multibuffer = MultiBuffer::new(0);
2296//         multibuffer.push_excerpts(
2297//             toml_buffer.clone(),
2298//             [ExcerptRange {
2299//                 context: Point::new(0, 0)..Point::new(2, 0),
2300//                 primary: None,
2301//             }],
2302//             cx,
2303//         );
2304//         multibuffer.push_excerpts(
2305//             rust_buffer.clone(),
2306//             [ExcerptRange {
2307//                 context: Point::new(0, 0)..Point::new(1, 0),
2308//                 primary: None,
2309//             }],
2310//             cx,
2311//         );
2312//         multibuffer
2313//     });
2314
2315//     cx.add_window(|cx| {
2316//         let mut editor = build_editor(multibuffer, cx);
2317
2318//         assert_eq!(
2319//             editor.text(cx),
2320//             indoc! {"
2321//                 a = 1
2322//                 b = 2
2323
2324//                 const c: usize = 3;
2325//             "}
2326//         );
2327
2328//         select_ranges(
2329//             &mut editor,
2330//             indoc! {"
2331//                 «aˇ» = 1
2332//                 b = 2
2333
2334//                 «const c:ˇ» usize = 3;
2335//             "},
2336//             cx,
2337//         );
2338
2339//         editor.tab(&Tab, cx);
2340//         assert_text_with_selections(
2341//             &mut editor,
2342//             indoc! {"
2343//                   «aˇ» = 1
2344//                 b = 2
2345
2346//                     «const c:ˇ» usize = 3;
2347//             "},
2348//             cx,
2349//         );
2350//         editor.tab_prev(&TabPrev, cx);
2351//         assert_text_with_selections(
2352//             &mut editor,
2353//             indoc! {"
2354//                 «aˇ» = 1
2355//                 b = 2
2356
2357//                 «const c:ˇ» usize = 3;
2358//             "},
2359//             cx,
2360//         );
2361
2362//         editor
2363//     });
2364// }
2365
2366// #[gpui::test]
2367// async fn test_backspace(cx: &mut gpui::TestAppContext) {
2368//     init_test(cx, |_| {});
2369
2370//     let mut cx = EditorTestContext::new(cx).await;
2371
2372//     // Basic backspace
2373//     cx.set_state(indoc! {"
2374//         onˇe two three
2375//         fou«rˇ» five six
2376//         seven «ˇeight nine
2377//         »ten
2378//     "});
2379//     cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
2380//     cx.assert_editor_state(indoc! {"
2381//         oˇe two three
2382//         fouˇ five six
2383//         seven ˇten
2384//     "});
2385
2386//     // Test backspace inside and around indents
2387//     cx.set_state(indoc! {"
2388//         zero
2389//             ˇone
2390//                 ˇtwo
2391//             ˇ ˇ ˇ  three
2392//         ˇ  ˇ  four
2393//     "});
2394//     cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
2395//     cx.assert_editor_state(indoc! {"
2396//         zero
2397//         ˇone
2398//             ˇtwo
2399//         ˇ  threeˇ  four
2400//     "});
2401
2402//     // Test backspace with line_mode set to true
2403//     cx.update_editor(|e, _| e.selections.line_mode = true);
2404//     cx.set_state(indoc! {"
2405//         The ˇquick ˇbrown
2406//         fox jumps over
2407//         the lazy dog
2408//         ˇThe qu«ick bˇ»rown"});
2409//     cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
2410//     cx.assert_editor_state(indoc! {"
2411//         ˇfox jumps over
2412//         the lazy dogˇ"});
2413// }
2414
2415// #[gpui::test]
2416// async fn test_delete(cx: &mut gpui::TestAppContext) {
2417//     init_test(cx, |_| {});
2418
2419//     let mut cx = EditorTestContext::new(cx).await;
2420//     cx.set_state(indoc! {"
2421//         onˇe two three
2422//         fou«rˇ» five six
2423//         seven «ˇeight nine
2424//         »ten
2425//     "});
2426//     cx.update_editor(|e, cx| e.delete(&Delete, cx));
2427//     cx.assert_editor_state(indoc! {"
2428//         onˇ two three
2429//         fouˇ five six
2430//         seven ˇten
2431//     "});
2432
2433//     // Test backspace with line_mode set to true
2434//     cx.update_editor(|e, _| e.selections.line_mode = true);
2435//     cx.set_state(indoc! {"
2436//         The ˇquick ˇbrown
2437//         fox «ˇjum»ps over
2438//         the lazy dog
2439//         ˇThe qu«ick bˇ»rown"});
2440//     cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
2441//     cx.assert_editor_state("ˇthe lazy dogˇ");
2442// }
2443
2444// #[gpui::test]
2445// fn test_delete_line(cx: &mut TestAppContext) {
2446//     init_test(cx, |_| {});
2447
2448//     let view = cx
2449//         .add_window(|cx| {
2450//             let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
2451//             build_editor(buffer, cx)
2452//         })
2453//         .root(cx);
2454//     view.update(cx, |view, cx| {
2455//         view.change_selections(None, cx, |s| {
2456//             s.select_display_ranges([
2457//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2458//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
2459//                 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
2460//             ])
2461//         });
2462//         view.delete_line(&DeleteLine, cx);
2463//         assert_eq!(view.display_text(cx), "ghi");
2464//         assert_eq!(
2465//             view.selections.display_ranges(cx),
2466//             vec![
2467//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
2468//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
2469//             ]
2470//         );
2471//     });
2472
2473//     let view = cx
2474//         .add_window(|cx| {
2475//             let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
2476//             build_editor(buffer, cx)
2477//         })
2478//         .root(cx);
2479//     view.update(cx, |view, cx| {
2480//         view.change_selections(None, cx, |s| {
2481//             s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
2482//         });
2483//         view.delete_line(&DeleteLine, cx);
2484//         assert_eq!(view.display_text(cx), "ghi\n");
2485//         assert_eq!(
2486//             view.selections.display_ranges(cx),
2487//             vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
2488//         );
2489//     });
2490// }
2491
2492// #[gpui::test]
2493// fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
2494//     init_test(cx, |_| {});
2495
2496//     cx.add_window(|cx| {
2497//         let buffer = MultiBuffer::build_simple("aaa\nbbb\nccc\nddd\n\n", cx);
2498//         let mut editor = build_editor(buffer.clone(), cx);
2499//         let buffer = buffer.read(cx).as_singleton().unwrap();
2500
2501//         assert_eq!(
2502//             editor.selections.ranges::<Point>(cx),
2503//             &[Point::new(0, 0)..Point::new(0, 0)]
2504//         );
2505
2506//         // When on single line, replace newline at end by space
2507//         editor.join_lines(&JoinLines, cx);
2508//         assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
2509//         assert_eq!(
2510//             editor.selections.ranges::<Point>(cx),
2511//             &[Point::new(0, 3)..Point::new(0, 3)]
2512//         );
2513
2514//         // When multiple lines are selected, remove newlines that are spanned by the selection
2515//         editor.change_selections(None, cx, |s| {
2516//             s.select_ranges([Point::new(0, 5)..Point::new(2, 2)])
2517//         });
2518//         editor.join_lines(&JoinLines, cx);
2519//         assert_eq!(buffer.read(cx).text(), "aaa bbb ccc ddd\n\n");
2520//         assert_eq!(
2521//             editor.selections.ranges::<Point>(cx),
2522//             &[Point::new(0, 11)..Point::new(0, 11)]
2523//         );
2524
2525//         // Undo should be transactional
2526//         editor.undo(&Undo, cx);
2527//         assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n");
2528//         assert_eq!(
2529//             editor.selections.ranges::<Point>(cx),
2530//             &[Point::new(0, 5)..Point::new(2, 2)]
2531//         );
2532
2533//         // When joining an empty line don't insert a space
2534//         editor.change_selections(None, cx, |s| {
2535//             s.select_ranges([Point::new(2, 1)..Point::new(2, 2)])
2536//         });
2537//         editor.join_lines(&JoinLines, cx);
2538//         assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n");
2539//         assert_eq!(
2540//             editor.selections.ranges::<Point>(cx),
2541//             [Point::new(2, 3)..Point::new(2, 3)]
2542//         );
2543
2544//         // We can remove trailing newlines
2545//         editor.join_lines(&JoinLines, cx);
2546//         assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
2547//         assert_eq!(
2548//             editor.selections.ranges::<Point>(cx),
2549//             [Point::new(2, 3)..Point::new(2, 3)]
2550//         );
2551
2552//         // We don't blow up on the last line
2553//         editor.join_lines(&JoinLines, cx);
2554//         assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd");
2555//         assert_eq!(
2556//             editor.selections.ranges::<Point>(cx),
2557//             [Point::new(2, 3)..Point::new(2, 3)]
2558//         );
2559
2560//         // reset to test indentation
2561//         editor.buffer.update(cx, |buffer, cx| {
2562//             buffer.edit(
2563//                 [
2564//                     (Point::new(1, 0)..Point::new(1, 2), "  "),
2565//                     (Point::new(2, 0)..Point::new(2, 3), "  \n\td"),
2566//                 ],
2567//                 None,
2568//                 cx,
2569//             )
2570//         });
2571
2572//         // We remove any leading spaces
2573//         assert_eq!(buffer.read(cx).text(), "aaa bbb\n  c\n  \n\td");
2574//         editor.change_selections(None, cx, |s| {
2575//             s.select_ranges([Point::new(0, 1)..Point::new(0, 1)])
2576//         });
2577//         editor.join_lines(&JoinLines, cx);
2578//         assert_eq!(buffer.read(cx).text(), "aaa bbb c\n  \n\td");
2579
2580//         // We don't insert a space for a line containing only spaces
2581//         editor.join_lines(&JoinLines, cx);
2582//         assert_eq!(buffer.read(cx).text(), "aaa bbb c\n\td");
2583
2584//         // We ignore any leading tabs
2585//         editor.join_lines(&JoinLines, cx);
2586//         assert_eq!(buffer.read(cx).text(), "aaa bbb c d");
2587
2588//         editor
2589//     });
2590// }
2591
2592// #[gpui::test]
2593// fn test_join_lines_with_multi_selection(cx: &mut TestAppContext) {
2594//     init_test(cx, |_| {});
2595
2596//     cx.add_window(|cx| {
2597//         let buffer = MultiBuffer::build_simple("aaa\nbbb\nccc\nddd\n\n", cx);
2598//         let mut editor = build_editor(buffer.clone(), cx);
2599//         let buffer = buffer.read(cx).as_singleton().unwrap();
2600
2601//         editor.change_selections(None, cx, |s| {
2602//             s.select_ranges([
2603//                 Point::new(0, 2)..Point::new(1, 1),
2604//                 Point::new(1, 2)..Point::new(1, 2),
2605//                 Point::new(3, 1)..Point::new(3, 2),
2606//             ])
2607//         });
2608
2609//         editor.join_lines(&JoinLines, cx);
2610//         assert_eq!(buffer.read(cx).text(), "aaa bbb ccc\nddd\n");
2611
2612//         assert_eq!(
2613//             editor.selections.ranges::<Point>(cx),
2614//             [
2615//                 Point::new(0, 7)..Point::new(0, 7),
2616//                 Point::new(1, 3)..Point::new(1, 3)
2617//             ]
2618//         );
2619//         editor
2620//     });
2621// }
2622
2623// #[gpui::test]
2624// async fn test_manipulate_lines_with_single_selection(cx: &mut TestAppContext) {
2625//     init_test(cx, |_| {});
2626
2627//     let mut cx = EditorTestContext::new(cx).await;
2628
2629//     // Test sort_lines_case_insensitive()
2630//     cx.set_state(indoc! {"
2631//         «z
2632//         y
2633//         x
2634//         Z
2635//         Y
2636//         Xˇ»
2637//     "});
2638//     cx.update_editor(|e, cx| e.sort_lines_case_insensitive(&SortLinesCaseInsensitive, cx));
2639//     cx.assert_editor_state(indoc! {"
2640//         «x
2641//         X
2642//         y
2643//         Y
2644//         z
2645//         Zˇ»
2646//     "});
2647
2648//     // Test reverse_lines()
2649//     cx.set_state(indoc! {"
2650//         «5
2651//         4
2652//         3
2653//         2
2654//         1ˇ»
2655//     "});
2656//     cx.update_editor(|e, cx| e.reverse_lines(&ReverseLines, cx));
2657//     cx.assert_editor_state(indoc! {"
2658//         «1
2659//         2
2660//         3
2661//         4
2662//         5ˇ»
2663//     "});
2664
2665//     // Skip testing shuffle_line()
2666
2667//     // From here on out, test more complex cases of manipulate_lines() with a single driver method: sort_lines_case_sensitive()
2668//     // Since all methods calling manipulate_lines() are doing the exact same general thing (reordering lines)
2669
2670//     // Don't manipulate when cursor is on single line, but expand the selection
2671//     cx.set_state(indoc! {"
2672//         ddˇdd
2673//         ccc
2674//         bb
2675//         a
2676//     "});
2677//     cx.update_editor(|e, cx| e.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx));
2678//     cx.assert_editor_state(indoc! {"
2679//         «ddddˇ»
2680//         ccc
2681//         bb
2682//         a
2683//     "});
2684
2685//     // Basic manipulate case
2686//     // Start selection moves to column 0
2687//     // End of selection shrinks to fit shorter line
2688//     cx.set_state(indoc! {"
2689//         dd«d
2690//         ccc
2691//         bb
2692//         aaaaaˇ»
2693//     "});
2694//     cx.update_editor(|e, cx| e.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx));
2695//     cx.assert_editor_state(indoc! {"
2696//         «aaaaa
2697//         bb
2698//         ccc
2699//         dddˇ»
2700//     "});
2701
2702//     // Manipulate case with newlines
2703//     cx.set_state(indoc! {"
2704//         dd«d
2705//         ccc
2706
2707//         bb
2708//         aaaaa
2709
2710//         ˇ»
2711//     "});
2712//     cx.update_editor(|e, cx| e.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx));
2713//     cx.assert_editor_state(indoc! {"
2714//         «
2715
2716//         aaaaa
2717//         bb
2718//         ccc
2719//         dddˇ»
2720
2721//     "});
2722// }
2723
2724// #[gpui::test]
2725// async fn test_manipulate_lines_with_multi_selection(cx: &mut TestAppContext) {
2726//     init_test(cx, |_| {});
2727
2728//     let mut cx = EditorTestContext::new(cx).await;
2729
2730//     // Manipulate with multiple selections on a single line
2731//     cx.set_state(indoc! {"
2732//         dd«dd
2733//         cˇ»c«c
2734//         bb
2735//         aaaˇ»aa
2736//     "});
2737//     cx.update_editor(|e, cx| e.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx));
2738//     cx.assert_editor_state(indoc! {"
2739//         «aaaaa
2740//         bb
2741//         ccc
2742//         ddddˇ»
2743//     "});
2744
2745//     // Manipulate with multiple disjoin selections
2746//     cx.set_state(indoc! {"
2747//         5«
2748//         4
2749//         3
2750//         2
2751//         1ˇ»
2752
2753//         dd«dd
2754//         ccc
2755//         bb
2756//         aaaˇ»aa
2757//     "});
2758//     cx.update_editor(|e, cx| e.sort_lines_case_sensitive(&SortLinesCaseSensitive, cx));
2759//     cx.assert_editor_state(indoc! {"
2760//         «1
2761//         2
2762//         3
2763//         4
2764//         5ˇ»
2765
2766//         «aaaaa
2767//         bb
2768//         ccc
2769//         ddddˇ»
2770//     "});
2771// }
2772
2773// #[gpui::test]
2774// async fn test_manipulate_text(cx: &mut TestAppContext) {
2775//     init_test(cx, |_| {});
2776
2777//     let mut cx = EditorTestContext::new(cx).await;
2778
2779//     // Test convert_to_upper_case()
2780//     cx.set_state(indoc! {"
2781//         «hello worldˇ»
2782//     "});
2783//     cx.update_editor(|e, cx| e.convert_to_upper_case(&ConvertToUpperCase, cx));
2784//     cx.assert_editor_state(indoc! {"
2785//         «HELLO WORLDˇ»
2786//     "});
2787
2788//     // Test convert_to_lower_case()
2789//     cx.set_state(indoc! {"
2790//         «HELLO WORLDˇ»
2791//     "});
2792//     cx.update_editor(|e, cx| e.convert_to_lower_case(&ConvertToLowerCase, cx));
2793//     cx.assert_editor_state(indoc! {"
2794//         «hello worldˇ»
2795//     "});
2796
2797//     // Test multiple line, single selection case
2798//     // Test code hack that covers the fact that to_case crate doesn't support '\n' as a word boundary
2799//     cx.set_state(indoc! {"
2800//         «The quick brown
2801//         fox jumps over
2802//         the lazy dogˇ»
2803//     "});
2804//     cx.update_editor(|e, cx| e.convert_to_title_case(&ConvertToTitleCase, cx));
2805//     cx.assert_editor_state(indoc! {"
2806//         «The Quick Brown
2807//         Fox Jumps Over
2808//         The Lazy Dogˇ»
2809//     "});
2810
2811//     // Test multiple line, single selection case
2812//     // Test code hack that covers the fact that to_case crate doesn't support '\n' as a word boundary
2813//     cx.set_state(indoc! {"
2814//         «The quick brown
2815//         fox jumps over
2816//         the lazy dogˇ»
2817//     "});
2818//     cx.update_editor(|e, cx| e.convert_to_upper_camel_case(&ConvertToUpperCamelCase, cx));
2819//     cx.assert_editor_state(indoc! {"
2820//         «TheQuickBrown
2821//         FoxJumpsOver
2822//         TheLazyDogˇ»
2823//     "});
2824
2825//     // From here on out, test more complex cases of manipulate_text()
2826
2827//     // Test no selection case - should affect words cursors are in
2828//     // Cursor at beginning, middle, and end of word
2829//     cx.set_state(indoc! {"
2830//         ˇhello big beauˇtiful worldˇ
2831//     "});
2832//     cx.update_editor(|e, cx| e.convert_to_upper_case(&ConvertToUpperCase, cx));
2833//     cx.assert_editor_state(indoc! {"
2834//         «HELLOˇ» big «BEAUTIFULˇ» «WORLDˇ»
2835//     "});
2836
2837//     // Test multiple selections on a single line and across multiple lines
2838//     cx.set_state(indoc! {"
2839//         «Theˇ» quick «brown
2840//         foxˇ» jumps «overˇ»
2841//         the «lazyˇ» dog
2842//     "});
2843//     cx.update_editor(|e, cx| e.convert_to_upper_case(&ConvertToUpperCase, cx));
2844//     cx.assert_editor_state(indoc! {"
2845//         «THEˇ» quick «BROWN
2846//         FOXˇ» jumps «OVERˇ»
2847//         the «LAZYˇ» dog
2848//     "});
2849
2850//     // Test case where text length grows
2851//     cx.set_state(indoc! {"
2852//         «tschüߡ»
2853//     "});
2854//     cx.update_editor(|e, cx| e.convert_to_upper_case(&ConvertToUpperCase, cx));
2855//     cx.assert_editor_state(indoc! {"
2856//         «TSCHÜSSˇ»
2857//     "});
2858
2859//     // Test to make sure we don't crash when text shrinks
2860//     cx.set_state(indoc! {"
2861//         aaa_bbbˇ
2862//     "});
2863//     cx.update_editor(|e, cx| e.convert_to_lower_camel_case(&ConvertToLowerCamelCase, cx));
2864//     cx.assert_editor_state(indoc! {"
2865//         «aaaBbbˇ»
2866//     "});
2867
2868//     // Test to make sure we all aware of the fact that each word can grow and shrink
2869//     // Final selections should be aware of this fact
2870//     cx.set_state(indoc! {"
2871//         aaa_bˇbb bbˇb_ccc ˇccc_ddd
2872//     "});
2873//     cx.update_editor(|e, cx| e.convert_to_lower_camel_case(&ConvertToLowerCamelCase, cx));
2874//     cx.assert_editor_state(indoc! {"
2875//         «aaaBbbˇ» «bbbCccˇ» «cccDddˇ»
2876//     "});
2877// }
2878
2879// #[gpui::test]
2880// fn test_duplicate_line(cx: &mut TestAppContext) {
2881//     init_test(cx, |_| {});
2882
2883//     let view = cx
2884//         .add_window(|cx| {
2885//             let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
2886//             build_editor(buffer, cx)
2887//         })
2888//         .root(cx);
2889//     view.update(cx, |view, cx| {
2890//         view.change_selections(None, cx, |s| {
2891//             s.select_display_ranges([
2892//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
2893//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
2894//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
2895//                 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
2896//             ])
2897//         });
2898//         view.duplicate_line(&DuplicateLine, cx);
2899//         assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
2900//         assert_eq!(
2901//             view.selections.display_ranges(cx),
2902//             vec![
2903//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
2904//                 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
2905//                 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
2906//                 DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
2907//             ]
2908//         );
2909//     });
2910
2911//     let view = cx
2912//         .add_window(|cx| {
2913//             let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
2914//             build_editor(buffer, cx)
2915//         })
2916//         .root(cx);
2917//     view.update(cx, |view, cx| {
2918//         view.change_selections(None, cx, |s| {
2919//             s.select_display_ranges([
2920//                 DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
2921//                 DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
2922//             ])
2923//         });
2924//         view.duplicate_line(&DuplicateLine, cx);
2925//         assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
2926//         assert_eq!(
2927//             view.selections.display_ranges(cx),
2928//             vec![
2929//                 DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
2930//                 DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
2931//             ]
2932//         );
2933//     });
2934// }
2935
2936// #[gpui::test]
2937// fn test_move_line_up_down(cx: &mut TestAppContext) {
2938//     init_test(cx, |_| {});
2939
2940//     let view = cx
2941//         .add_window(|cx| {
2942//             let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
2943//             build_editor(buffer, cx)
2944//         })
2945//         .root(cx);
2946//     view.update(cx, |view, cx| {
2947//         view.fold_ranges(
2948//             vec![
2949//                 Point::new(0, 2)..Point::new(1, 2),
2950//                 Point::new(2, 3)..Point::new(4, 1),
2951//                 Point::new(7, 0)..Point::new(8, 4),
2952//             ],
2953//             true,
2954//             cx,
2955//         );
2956//         view.change_selections(None, cx, |s| {
2957//             s.select_display_ranges([
2958//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2959//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
2960//                 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
2961//                 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
2962//             ])
2963//         });
2964//         assert_eq!(
2965//             view.display_text(cx),
2966//             "aa⋯bbb\nccc⋯eeee\nfffff\nggggg\n⋯i\njjjjj"
2967//         );
2968
2969//         view.move_line_up(&MoveLineUp, cx);
2970//         assert_eq!(
2971//             view.display_text(cx),
2972//             "aa⋯bbb\nccc⋯eeee\nggggg\n⋯i\njjjjj\nfffff"
2973//         );
2974//         assert_eq!(
2975//             view.selections.display_ranges(cx),
2976//             vec![
2977//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2978//                 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
2979//                 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
2980//                 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
2981//             ]
2982//         );
2983//     });
2984
2985//     view.update(cx, |view, cx| {
2986//         view.move_line_down(&MoveLineDown, cx);
2987//         assert_eq!(
2988//             view.display_text(cx),
2989//             "ccc⋯eeee\naa⋯bbb\nfffff\nggggg\n⋯i\njjjjj"
2990//         );
2991//         assert_eq!(
2992//             view.selections.display_ranges(cx),
2993//             vec![
2994//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
2995//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
2996//                 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
2997//                 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
2998//             ]
2999//         );
3000//     });
3001
3002//     view.update(cx, |view, cx| {
3003//         view.move_line_down(&MoveLineDown, cx);
3004//         assert_eq!(
3005//             view.display_text(cx),
3006//             "ccc⋯eeee\nfffff\naa⋯bbb\nggggg\n⋯i\njjjjj"
3007//         );
3008//         assert_eq!(
3009//             view.selections.display_ranges(cx),
3010//             vec![
3011//                 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3012//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3013//                 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3014//                 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
3015//             ]
3016//         );
3017//     });
3018
3019//     view.update(cx, |view, cx| {
3020//         view.move_line_up(&MoveLineUp, cx);
3021//         assert_eq!(
3022//             view.display_text(cx),
3023//             "ccc⋯eeee\naa⋯bbb\nggggg\n⋯i\njjjjj\nfffff"
3024//         );
3025//         assert_eq!(
3026//             view.selections.display_ranges(cx),
3027//             vec![
3028//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3029//                 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3030//                 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
3031//                 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
3032//             ]
3033//         );
3034//     });
3035// }
3036
3037// #[gpui::test]
3038// fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
3039//     init_test(cx, |_| {});
3040
3041//     let editor = cx
3042//         .add_window(|cx| {
3043//             let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
3044//             build_editor(buffer, cx)
3045//         })
3046//         .root(cx);
3047//     editor.update(cx, |editor, cx| {
3048//         let snapshot = editor.buffer.read(cx).snapshot(cx);
3049//         editor.insert_blocks(
3050//             [BlockProperties {
3051//                 style: BlockStyle::Fixed,
3052//                 position: snapshot.anchor_after(Point::new(2, 0)),
3053//                 disposition: BlockDisposition::Below,
3054//                 height: 1,
3055//                 render: Arc::new(|_| Empty::new().into_any()),
3056//             }],
3057//             Some(Autoscroll::fit()),
3058//             cx,
3059//         );
3060//         editor.change_selections(None, cx, |s| {
3061//             s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
3062//         });
3063//         editor.move_line_down(&MoveLineDown, cx);
3064//     });
3065// }
3066
3067// #[gpui::test]
3068// fn test_transpose(cx: &mut TestAppContext) {
3069//     init_test(cx, |_| {});
3070
3071//     _ = cx.add_window(|cx| {
3072//         let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
3073
3074//         editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
3075//         editor.transpose(&Default::default(), cx);
3076//         assert_eq!(editor.text(cx), "bac");
3077//         assert_eq!(editor.selections.ranges(cx), [2..2]);
3078
3079//         editor.transpose(&Default::default(), cx);
3080//         assert_eq!(editor.text(cx), "bca");
3081//         assert_eq!(editor.selections.ranges(cx), [3..3]);
3082
3083//         editor.transpose(&Default::default(), cx);
3084//         assert_eq!(editor.text(cx), "bac");
3085//         assert_eq!(editor.selections.ranges(cx), [3..3]);
3086
3087//         editor
3088//     });
3089
3090//     _ = cx.add_window(|cx| {
3091//         let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
3092
3093//         editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
3094//         editor.transpose(&Default::default(), cx);
3095//         assert_eq!(editor.text(cx), "acb\nde");
3096//         assert_eq!(editor.selections.ranges(cx), [3..3]);
3097
3098//         editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
3099//         editor.transpose(&Default::default(), cx);
3100//         assert_eq!(editor.text(cx), "acbd\ne");
3101//         assert_eq!(editor.selections.ranges(cx), [5..5]);
3102
3103//         editor.transpose(&Default::default(), cx);
3104//         assert_eq!(editor.text(cx), "acbde\n");
3105//         assert_eq!(editor.selections.ranges(cx), [6..6]);
3106
3107//         editor.transpose(&Default::default(), cx);
3108//         assert_eq!(editor.text(cx), "acbd\ne");
3109//         assert_eq!(editor.selections.ranges(cx), [6..6]);
3110
3111//         editor
3112//     });
3113
3114//     _ = cx.add_window(|cx| {
3115//         let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
3116
3117//         editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
3118//         editor.transpose(&Default::default(), cx);
3119//         assert_eq!(editor.text(cx), "bacd\ne");
3120//         assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
3121
3122//         editor.transpose(&Default::default(), cx);
3123//         assert_eq!(editor.text(cx), "bcade\n");
3124//         assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
3125
3126//         editor.transpose(&Default::default(), cx);
3127//         assert_eq!(editor.text(cx), "bcda\ne");
3128//         assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
3129
3130//         editor.transpose(&Default::default(), cx);
3131//         assert_eq!(editor.text(cx), "bcade\n");
3132//         assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
3133
3134//         editor.transpose(&Default::default(), cx);
3135//         assert_eq!(editor.text(cx), "bcaed\n");
3136//         assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
3137
3138//         editor
3139//     });
3140
3141//     _ = cx.add_window(|cx| {
3142//         let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
3143
3144//         editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
3145//         editor.transpose(&Default::default(), cx);
3146//         assert_eq!(editor.text(cx), "🏀🍐✋");
3147//         assert_eq!(editor.selections.ranges(cx), [8..8]);
3148
3149//         editor.transpose(&Default::default(), cx);
3150//         assert_eq!(editor.text(cx), "🏀✋🍐");
3151//         assert_eq!(editor.selections.ranges(cx), [11..11]);
3152
3153//         editor.transpose(&Default::default(), cx);
3154//         assert_eq!(editor.text(cx), "🏀🍐✋");
3155//         assert_eq!(editor.selections.ranges(cx), [11..11]);
3156
3157//         editor
3158//     });
3159// }
3160
3161// #[gpui::test]
3162// async fn test_clipboard(cx: &mut gpui::TestAppContext) {
3163//     init_test(cx, |_| {});
3164
3165//     let mut cx = EditorTestContext::new(cx).await;
3166
3167//     cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
3168//     cx.update_editor(|e, cx| e.cut(&Cut, cx));
3169//     cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
3170
3171//     // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
3172//     cx.set_state("two ˇfour ˇsix ˇ");
3173//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3174//     cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
3175
3176//     // Paste again but with only two cursors. Since the number of cursors doesn't
3177//     // match the number of slices in the clipboard, the entire clipboard text
3178//     // is pasted at each cursor.
3179//     cx.set_state("ˇtwo one✅ four three six five ˇ");
3180//     cx.update_editor(|e, cx| {
3181//         e.handle_input("( ", cx);
3182//         e.paste(&Paste, cx);
3183//         e.handle_input(") ", cx);
3184//     });
3185//     cx.assert_editor_state(
3186//         &([
3187//             "( one✅ ",
3188//             "three ",
3189//             "five ) ˇtwo one✅ four three six five ( one✅ ",
3190//             "three ",
3191//             "five ) ˇ",
3192//         ]
3193//         .join("\n")),
3194//     );
3195
3196//     // Cut with three selections, one of which is full-line.
3197//     cx.set_state(indoc! {"
3198//         1«2ˇ»3
3199//         4ˇ567
3200//         «8ˇ»9"});
3201//     cx.update_editor(|e, cx| e.cut(&Cut, cx));
3202//     cx.assert_editor_state(indoc! {"
3203//         1ˇ3
3204//         ˇ9"});
3205
3206//     // Paste with three selections, noticing how the copied selection that was full-line
3207//     // gets inserted before the second cursor.
3208//     cx.set_state(indoc! {"
3209//         1ˇ3
3210//         9ˇ
3211//         «oˇ»ne"});
3212//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3213//     cx.assert_editor_state(indoc! {"
3214//         12ˇ3
3215//         4567
3216//         9ˇ
3217//         8ˇne"});
3218
3219//     // Copy with a single cursor only, which writes the whole line into the clipboard.
3220//     cx.set_state(indoc! {"
3221//         The quick brown
3222//         fox juˇmps over
3223//         the lazy dog"});
3224//     cx.update_editor(|e, cx| e.copy(&Copy, cx));
3225//     cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
3226
3227//     // Paste with three selections, noticing how the copied full-line selection is inserted
3228//     // before the empty selections but replaces the selection that is non-empty.
3229//     cx.set_state(indoc! {"
3230//         Tˇhe quick brown
3231//         «foˇ»x jumps over
3232//         tˇhe lazy dog"});
3233//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3234//     cx.assert_editor_state(indoc! {"
3235//         fox jumps over
3236//         Tˇhe quick brown
3237//         fox jumps over
3238//         ˇx jumps over
3239//         fox jumps over
3240//         tˇhe lazy dog"});
3241// }
3242
3243// #[gpui::test]
3244// async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
3245//     init_test(cx, |_| {});
3246
3247//     let mut cx = EditorTestContext::new(cx).await;
3248//     let language = Arc::new(Language::new(
3249//         LanguageConfig::default(),
3250//         Some(tree_sitter_rust::language()),
3251//     ));
3252//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
3253
3254//     // Cut an indented block, without the leading whitespace.
3255//     cx.set_state(indoc! {"
3256//         const a: B = (
3257//             c(),
3258//             «d(
3259//                 e,
3260//                 f
3261//             )ˇ»
3262//         );
3263//     "});
3264//     cx.update_editor(|e, cx| e.cut(&Cut, cx));
3265//     cx.assert_editor_state(indoc! {"
3266//         const a: B = (
3267//             c(),
3268//             ˇ
3269//         );
3270//     "});
3271
3272//     // Paste it at the same position.
3273//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3274//     cx.assert_editor_state(indoc! {"
3275//         const a: B = (
3276//             c(),
3277//             d(
3278//                 e,
3279//                 f
3280//             )ˇ
3281//         );
3282//     "});
3283
3284//     // Paste it at a line with a lower indent level.
3285//     cx.set_state(indoc! {"
3286//         ˇ
3287//         const a: B = (
3288//             c(),
3289//         );
3290//     "});
3291//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3292//     cx.assert_editor_state(indoc! {"
3293//         d(
3294//             e,
3295//             f
3296//         )ˇ
3297//         const a: B = (
3298//             c(),
3299//         );
3300//     "});
3301
3302//     // Cut an indented block, with the leading whitespace.
3303//     cx.set_state(indoc! {"
3304//         const a: B = (
3305//             c(),
3306//         «    d(
3307//                 e,
3308//                 f
3309//             )
3310//         ˇ»);
3311//     "});
3312//     cx.update_editor(|e, cx| e.cut(&Cut, cx));
3313//     cx.assert_editor_state(indoc! {"
3314//         const a: B = (
3315//             c(),
3316//         ˇ);
3317//     "});
3318
3319//     // Paste it at the same position.
3320//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3321//     cx.assert_editor_state(indoc! {"
3322//         const a: B = (
3323//             c(),
3324//             d(
3325//                 e,
3326//                 f
3327//             )
3328//         ˇ);
3329//     "});
3330
3331//     // Paste it at a line with a higher indent level.
3332//     cx.set_state(indoc! {"
3333//         const a: B = (
3334//             c(),
3335//             d(
3336//                 e,
3337//                 fˇ
3338//             )
3339//         );
3340//     "});
3341//     cx.update_editor(|e, cx| e.paste(&Paste, cx));
3342//     cx.assert_editor_state(indoc! {"
3343//         const a: B = (
3344//             c(),
3345//             d(
3346//                 e,
3347//                 f    d(
3348//                     e,
3349//                     f
3350//                 )
3351//         ˇ
3352//             )
3353//         );
3354//     "});
3355// }
3356
3357// #[gpui::test]
3358// fn test_select_all(cx: &mut TestAppContext) {
3359//     init_test(cx, |_| {});
3360
3361//     let view = cx
3362//         .add_window(|cx| {
3363//             let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
3364//             build_editor(buffer, cx)
3365//         })
3366//         .root(cx);
3367//     view.update(cx, |view, cx| {
3368//         view.select_all(&SelectAll, cx);
3369//         assert_eq!(
3370//             view.selections.display_ranges(cx),
3371//             &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
3372//         );
3373//     });
3374// }
3375
3376// #[gpui::test]
3377// fn test_select_line(cx: &mut TestAppContext) {
3378//     init_test(cx, |_| {});
3379
3380//     let view = cx
3381//         .add_window(|cx| {
3382//             let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
3383//             build_editor(buffer, cx)
3384//         })
3385//         .root(cx);
3386//     view.update(cx, |view, cx| {
3387//         view.change_selections(None, cx, |s| {
3388//             s.select_display_ranges([
3389//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3390//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3391//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3392//                 DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
3393//             ])
3394//         });
3395//         view.select_line(&SelectLine, cx);
3396//         assert_eq!(
3397//             view.selections.display_ranges(cx),
3398//             vec![
3399//                 DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
3400//                 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
3401//             ]
3402//         );
3403//     });
3404
3405//     view.update(cx, |view, cx| {
3406//         view.select_line(&SelectLine, cx);
3407//         assert_eq!(
3408//             view.selections.display_ranges(cx),
3409//             vec![
3410//                 DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
3411//                 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
3412//             ]
3413//         );
3414//     });
3415
3416//     view.update(cx, |view, cx| {
3417//         view.select_line(&SelectLine, cx);
3418//         assert_eq!(
3419//             view.selections.display_ranges(cx),
3420//             vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
3421//         );
3422//     });
3423// }
3424
3425// #[gpui::test]
3426// fn test_split_selection_into_lines(cx: &mut TestAppContext) {
3427//     init_test(cx, |_| {});
3428
3429//     let view = cx
3430//         .add_window(|cx| {
3431//             let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
3432//             build_editor(buffer, cx)
3433//         })
3434//         .root(cx);
3435//     view.update(cx, |view, cx| {
3436//         view.fold_ranges(
3437//             vec![
3438//                 Point::new(0, 2)..Point::new(1, 2),
3439//                 Point::new(2, 3)..Point::new(4, 1),
3440//                 Point::new(7, 0)..Point::new(8, 4),
3441//             ],
3442//             true,
3443//             cx,
3444//         );
3445//         view.change_selections(None, cx, |s| {
3446//             s.select_display_ranges([
3447//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3448//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3449//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3450//                 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
3451//             ])
3452//         });
3453//         assert_eq!(view.display_text(cx), "aa⋯bbb\nccc⋯eeee\nfffff\nggggg\n⋯i");
3454//     });
3455
3456//     view.update(cx, |view, cx| {
3457//         view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
3458//         assert_eq!(
3459//             view.display_text(cx),
3460//             "aaaaa\nbbbbb\nccc⋯eeee\nfffff\nggggg\n⋯i"
3461//         );
3462//         assert_eq!(
3463//             view.selections.display_ranges(cx),
3464//             [
3465//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3466//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3467//                 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
3468//                 DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
3469//             ]
3470//         );
3471//     });
3472
3473//     view.update(cx, |view, cx| {
3474//         view.change_selections(None, cx, |s| {
3475//             s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
3476//         });
3477//         view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
3478//         assert_eq!(
3479//             view.display_text(cx),
3480//             "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
3481//         );
3482//         assert_eq!(
3483//             view.selections.display_ranges(cx),
3484//             [
3485//                 DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
3486//                 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3487//                 DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
3488//                 DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
3489//                 DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
3490//                 DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
3491//                 DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
3492//                 DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
3493//             ]
3494//         );
3495//     });
3496// }
3497
3498// #[gpui::test]
3499// fn test_add_selection_above_below(cx: &mut TestAppContext) {
3500//     init_test(cx, |_| {});
3501
3502//     let view = cx
3503//         .add_window(|cx| {
3504//             let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
3505//             build_editor(buffer, cx)
3506//         })
3507//         .root(cx);
3508
3509//     view.update(cx, |view, cx| {
3510//         view.change_selections(None, cx, |s| {
3511//             s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
3512//         });
3513//     });
3514//     view.update(cx, |view, cx| {
3515//         view.add_selection_above(&AddSelectionAbove, cx);
3516//         assert_eq!(
3517//             view.selections.display_ranges(cx),
3518//             vec![
3519//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3520//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
3521//             ]
3522//         );
3523//     });
3524
3525//     view.update(cx, |view, cx| {
3526//         view.add_selection_above(&AddSelectionAbove, cx);
3527//         assert_eq!(
3528//             view.selections.display_ranges(cx),
3529//             vec![
3530//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3531//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
3532//             ]
3533//         );
3534//     });
3535
3536//     view.update(cx, |view, cx| {
3537//         view.add_selection_below(&AddSelectionBelow, cx);
3538//         assert_eq!(
3539//             view.selections.display_ranges(cx),
3540//             vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
3541//         );
3542
3543//         view.undo_selection(&UndoSelection, cx);
3544//         assert_eq!(
3545//             view.selections.display_ranges(cx),
3546//             vec![
3547//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3548//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
3549//             ]
3550//         );
3551
3552//         view.redo_selection(&RedoSelection, cx);
3553//         assert_eq!(
3554//             view.selections.display_ranges(cx),
3555//             vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
3556//         );
3557//     });
3558
3559//     view.update(cx, |view, cx| {
3560//         view.add_selection_below(&AddSelectionBelow, cx);
3561//         assert_eq!(
3562//             view.selections.display_ranges(cx),
3563//             vec![
3564//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
3565//                 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
3566//             ]
3567//         );
3568//     });
3569
3570//     view.update(cx, |view, cx| {
3571//         view.add_selection_below(&AddSelectionBelow, cx);
3572//         assert_eq!(
3573//             view.selections.display_ranges(cx),
3574//             vec![
3575//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
3576//                 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
3577//             ]
3578//         );
3579//     });
3580
3581//     view.update(cx, |view, cx| {
3582//         view.change_selections(None, cx, |s| {
3583//             s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
3584//         });
3585//     });
3586//     view.update(cx, |view, cx| {
3587//         view.add_selection_below(&AddSelectionBelow, cx);
3588//         assert_eq!(
3589//             view.selections.display_ranges(cx),
3590//             vec![
3591//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3592//                 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
3593//             ]
3594//         );
3595//     });
3596
3597//     view.update(cx, |view, cx| {
3598//         view.add_selection_below(&AddSelectionBelow, cx);
3599//         assert_eq!(
3600//             view.selections.display_ranges(cx),
3601//             vec![
3602//                 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3603//                 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
3604//             ]
3605//         );
3606//     });
3607
3608//     view.update(cx, |view, cx| {
3609//         view.add_selection_above(&AddSelectionAbove, cx);
3610//         assert_eq!(
3611//             view.selections.display_ranges(cx),
3612//             vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
3613//         );
3614//     });
3615
3616//     view.update(cx, |view, cx| {
3617//         view.add_selection_above(&AddSelectionAbove, cx);
3618//         assert_eq!(
3619//             view.selections.display_ranges(cx),
3620//             vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
3621//         );
3622//     });
3623
3624//     view.update(cx, |view, cx| {
3625//         view.change_selections(None, cx, |s| {
3626//             s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
3627//         });
3628//         view.add_selection_below(&AddSelectionBelow, cx);
3629//         assert_eq!(
3630//             view.selections.display_ranges(cx),
3631//             vec![
3632//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3633//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3634//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3635//             ]
3636//         );
3637//     });
3638
3639//     view.update(cx, |view, cx| {
3640//         view.add_selection_below(&AddSelectionBelow, cx);
3641//         assert_eq!(
3642//             view.selections.display_ranges(cx),
3643//             vec![
3644//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3645//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3646//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3647//                 DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
3648//             ]
3649//         );
3650//     });
3651
3652//     view.update(cx, |view, cx| {
3653//         view.add_selection_above(&AddSelectionAbove, cx);
3654//         assert_eq!(
3655//             view.selections.display_ranges(cx),
3656//             vec![
3657//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3658//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3659//                 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3660//             ]
3661//         );
3662//     });
3663
3664//     view.update(cx, |view, cx| {
3665//         view.change_selections(None, cx, |s| {
3666//             s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
3667//         });
3668//     });
3669//     view.update(cx, |view, cx| {
3670//         view.add_selection_above(&AddSelectionAbove, cx);
3671//         assert_eq!(
3672//             view.selections.display_ranges(cx),
3673//             vec![
3674//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
3675//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
3676//                 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
3677//                 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
3678//             ]
3679//         );
3680//     });
3681
3682//     view.update(cx, |view, cx| {
3683//         view.add_selection_below(&AddSelectionBelow, cx);
3684//         assert_eq!(
3685//             view.selections.display_ranges(cx),
3686//             vec![
3687//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
3688//                 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
3689//                 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
3690//             ]
3691//         );
3692//     });
3693// }
3694
3695// #[gpui::test]
3696// async fn test_select_next(cx: &mut gpui::TestAppContext) {
3697//     init_test(cx, |_| {});
3698
3699//     let mut cx = EditorTestContext::new(cx).await;
3700//     cx.set_state("abc\nˇabc abc\ndefabc\nabc");
3701
3702//     cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx))
3703//         .unwrap();
3704//     cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
3705
3706//     cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx))
3707//         .unwrap();
3708//     cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
3709
3710//     cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
3711//     cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
3712
3713//     cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
3714//     cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
3715
3716//     cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx))
3717//         .unwrap();
3718//     cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
3719
3720//     cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx))
3721//         .unwrap();
3722//     cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
3723// }
3724
3725// #[gpui::test]
3726// async fn test_select_previous(cx: &mut gpui::TestAppContext) {
3727//     init_test(cx, |_| {});
3728//     {
3729//         // `Select previous` without a selection (selects wordwise)
3730//         let mut cx = EditorTestContext::new(cx).await;
3731//         cx.set_state("abc\nˇabc abc\ndefabc\nabc");
3732
3733//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3734//             .unwrap();
3735//         cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
3736
3737//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3738//             .unwrap();
3739//         cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc");
3740
3741//         cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
3742//         cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
3743
3744//         cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
3745//         cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc");
3746
3747//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3748//             .unwrap();
3749//         cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\n«abcˇ»");
3750
3751//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3752//             .unwrap();
3753//         cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
3754//     }
3755//     {
3756//         // `Select previous` with a selection
3757//         let mut cx = EditorTestContext::new(cx).await;
3758//         cx.set_state("abc\n«ˇabc» abc\ndefabc\nabc");
3759
3760//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3761//             .unwrap();
3762//         cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\nabc");
3763
3764//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3765//             .unwrap();
3766//         cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»");
3767
3768//         cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
3769//         cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\nabc");
3770
3771//         cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
3772//         cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»");
3773
3774//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3775//             .unwrap();
3776//         cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndef«abcˇ»\n«abcˇ»");
3777
3778//         cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx))
3779//             .unwrap();
3780//         cx.assert_editor_state("«abcˇ»\n«ˇabc» «abcˇ»\ndef«abcˇ»\n«abcˇ»");
3781//     }
3782// }
3783
3784// #[gpui::test]
3785// async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
3786//     init_test(cx, |_| {});
3787
3788//     let language = Arc::new(Language::new(
3789//         LanguageConfig::default(),
3790//         Some(tree_sitter_rust::language()),
3791//     ));
3792
3793//     let text = r#"
3794//         use mod1::mod2::{mod3, mod4};
3795
3796//         fn fn_1(param1: bool, param2: &str) {
3797//             let var1 = "text";
3798//         }
3799//     "#
3800//     .unindent();
3801
3802//     let buffer =
3803//         cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx));
3804//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
3805//     let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
3806//     view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
3807//         .await;
3808
3809//     view.update(cx, |view, cx| {
3810//         view.change_selections(None, cx, |s| {
3811//             s.select_display_ranges([
3812//                 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
3813//                 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
3814//                 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
3815//             ]);
3816//         });
3817//         view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
3818//     });
3819//     assert_eq!(
3820//         view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
3821//         &[
3822//             DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
3823//             DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
3824//             DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
3825//         ]
3826//     );
3827
3828//     view.update(cx, |view, cx| {
3829//         view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
3830//     });
3831//     assert_eq!(
3832//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3833//         &[
3834//             DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
3835//             DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
3836//         ]
3837//     );
3838
3839//     view.update(cx, |view, cx| {
3840//         view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
3841//     });
3842//     assert_eq!(
3843//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3844//         &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
3845//     );
3846
3847//     // Trying to expand the selected syntax node one more time has no effect.
3848//     view.update(cx, |view, cx| {
3849//         view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
3850//     });
3851//     assert_eq!(
3852//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3853//         &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
3854//     );
3855
3856//     view.update(cx, |view, cx| {
3857//         view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
3858//     });
3859//     assert_eq!(
3860//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3861//         &[
3862//             DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
3863//             DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
3864//         ]
3865//     );
3866
3867//     view.update(cx, |view, cx| {
3868//         view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
3869//     });
3870//     assert_eq!(
3871//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3872//         &[
3873//             DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
3874//             DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
3875//             DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
3876//         ]
3877//     );
3878
3879//     view.update(cx, |view, cx| {
3880//         view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
3881//     });
3882//     assert_eq!(
3883//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3884//         &[
3885//             DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
3886//             DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
3887//             DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
3888//         ]
3889//     );
3890
3891//     // Trying to shrink the selected syntax node one more time has no effect.
3892//     view.update(cx, |view, cx| {
3893//         view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
3894//     });
3895//     assert_eq!(
3896//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3897//         &[
3898//             DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
3899//             DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
3900//             DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
3901//         ]
3902//     );
3903
3904//     // Ensure that we keep expanding the selection if the larger selection starts or ends within
3905//     // a fold.
3906//     view.update(cx, |view, cx| {
3907//         view.fold_ranges(
3908//             vec![
3909//                 Point::new(0, 21)..Point::new(0, 24),
3910//                 Point::new(3, 20)..Point::new(3, 22),
3911//             ],
3912//             true,
3913//             cx,
3914//         );
3915//         view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
3916//     });
3917//     assert_eq!(
3918//         view.update(cx, |view, cx| view.selections.display_ranges(cx)),
3919//         &[
3920//             DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
3921//             DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
3922//             DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
3923//         ]
3924//     );
3925// }
3926
3927// #[gpui::test]
3928// async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
3929//     init_test(cx, |_| {});
3930
3931//     let language = Arc::new(
3932//         Language::new(
3933//             LanguageConfig {
3934//                 brackets: BracketPairConfig {
3935//                     pairs: vec![
3936//                         BracketPair {
3937//                             start: "{".to_string(),
3938//                             end: "}".to_string(),
3939//                             close: false,
3940//                             newline: true,
3941//                         },
3942//                         BracketPair {
3943//                             start: "(".to_string(),
3944//                             end: ")".to_string(),
3945//                             close: false,
3946//                             newline: true,
3947//                         },
3948//                     ],
3949//                     ..Default::default()
3950//                 },
3951//                 ..Default::default()
3952//             },
3953//             Some(tree_sitter_rust::language()),
3954//         )
3955//         .with_indents_query(
3956//             r#"
3957//                 (_ "(" ")" @end) @indent
3958//                 (_ "{" "}" @end) @indent
3959//             "#,
3960//         )
3961//         .unwrap(),
3962//     );
3963
3964//     let text = "fn a() {}";
3965
3966//     let buffer =
3967//         cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx));
3968//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
3969//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
3970//     editor
3971//         .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
3972//         .await;
3973
3974//     editor.update(cx, |editor, cx| {
3975//         editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
3976//         editor.newline(&Newline, cx);
3977//         assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
3978//         assert_eq!(
3979//             editor.selections.ranges(cx),
3980//             &[
3981//                 Point::new(1, 4)..Point::new(1, 4),
3982//                 Point::new(3, 4)..Point::new(3, 4),
3983//                 Point::new(5, 0)..Point::new(5, 0)
3984//             ]
3985//         );
3986//     });
3987// }
3988
3989// #[gpui::test]
3990// async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
3991//     init_test(cx, |_| {});
3992
3993//     let mut cx = EditorTestContext::new(cx).await;
3994
3995//     let language = Arc::new(Language::new(
3996//         LanguageConfig {
3997//             brackets: BracketPairConfig {
3998//                 pairs: vec![
3999//                     BracketPair {
4000//                         start: "{".to_string(),
4001//                         end: "}".to_string(),
4002//                         close: true,
4003//                         newline: true,
4004//                     },
4005//                     BracketPair {
4006//                         start: "(".to_string(),
4007//                         end: ")".to_string(),
4008//                         close: true,
4009//                         newline: true,
4010//                     },
4011//                     BracketPair {
4012//                         start: "/*".to_string(),
4013//                         end: " */".to_string(),
4014//                         close: true,
4015//                         newline: true,
4016//                     },
4017//                     BracketPair {
4018//                         start: "[".to_string(),
4019//                         end: "]".to_string(),
4020//                         close: false,
4021//                         newline: true,
4022//                     },
4023//                     BracketPair {
4024//                         start: "\"".to_string(),
4025//                         end: "\"".to_string(),
4026//                         close: true,
4027//                         newline: false,
4028//                     },
4029//                 ],
4030//                 ..Default::default()
4031//             },
4032//             autoclose_before: "})]".to_string(),
4033//             ..Default::default()
4034//         },
4035//         Some(tree_sitter_rust::language()),
4036//     ));
4037
4038//     let registry = Arc::new(LanguageRegistry::test());
4039//     registry.add(language.clone());
4040//     cx.update_buffer(|buffer, cx| {
4041//         buffer.set_language_registry(registry);
4042//         buffer.set_language(Some(language), cx);
4043//     });
4044
4045//     cx.set_state(
4046//         &r#"
4047//             🏀ˇ
4048//             εˇ
4049//             ❤️ˇ
4050//         "#
4051//         .unindent(),
4052//     );
4053
4054//     // autoclose multiple nested brackets at multiple cursors
4055//     cx.update_editor(|view, cx| {
4056//         view.handle_input("{", cx);
4057//         view.handle_input("{", cx);
4058//         view.handle_input("{", cx);
4059//     });
4060//     cx.assert_editor_state(
4061//         &"
4062//             🏀{{{ˇ}}}
4063//             ε{{{ˇ}}}
4064//             ❤️{{{ˇ}}}
4065//         "
4066//         .unindent(),
4067//     );
4068
4069//     // insert a different closing bracket
4070//     cx.update_editor(|view, cx| {
4071//         view.handle_input(")", cx);
4072//     });
4073//     cx.assert_editor_state(
4074//         &"
4075//             🏀{{{)ˇ}}}
4076//             ε{{{)ˇ}}}
4077//             ❤️{{{)ˇ}}}
4078//         "
4079//         .unindent(),
4080//     );
4081
4082//     // skip over the auto-closed brackets when typing a closing bracket
4083//     cx.update_editor(|view, cx| {
4084//         view.move_right(&MoveRight, cx);
4085//         view.handle_input("}", cx);
4086//         view.handle_input("}", cx);
4087//         view.handle_input("}", cx);
4088//     });
4089//     cx.assert_editor_state(
4090//         &"
4091//             🏀{{{)}}}}ˇ
4092//             ε{{{)}}}}ˇ
4093//             ❤️{{{)}}}}ˇ
4094//         "
4095//         .unindent(),
4096//     );
4097
4098//     // autoclose multi-character pairs
4099//     cx.set_state(
4100//         &"
4101//             ˇ
4102//             ˇ
4103//         "
4104//         .unindent(),
4105//     );
4106//     cx.update_editor(|view, cx| {
4107//         view.handle_input("/", cx);
4108//         view.handle_input("*", cx);
4109//     });
4110//     cx.assert_editor_state(
4111//         &"
4112//             /*ˇ */
4113//             /*ˇ */
4114//         "
4115//         .unindent(),
4116//     );
4117
4118//     // one cursor autocloses a multi-character pair, one cursor
4119//     // does not autoclose.
4120//     cx.set_state(
4121//         &"
4122//             /ˇ
4123//             ˇ
4124//         "
4125//         .unindent(),
4126//     );
4127//     cx.update_editor(|view, cx| view.handle_input("*", cx));
4128//     cx.assert_editor_state(
4129//         &"
4130//             /*ˇ */
4131//             *ˇ
4132//         "
4133//         .unindent(),
4134//     );
4135
4136//     // Don't autoclose if the next character isn't whitespace and isn't
4137//     // listed in the language's "autoclose_before" section.
4138//     cx.set_state("ˇa b");
4139//     cx.update_editor(|view, cx| view.handle_input("{", cx));
4140//     cx.assert_editor_state("{ˇa b");
4141
4142//     // Don't autoclose if `close` is false for the bracket pair
4143//     cx.set_state("ˇ");
4144//     cx.update_editor(|view, cx| view.handle_input("[", cx));
4145//     cx.assert_editor_state("[ˇ");
4146
4147//     // Surround with brackets if text is selected
4148//     cx.set_state("«aˇ» b");
4149//     cx.update_editor(|view, cx| view.handle_input("{", cx));
4150//     cx.assert_editor_state("{«aˇ»} b");
4151
4152//     // Autclose pair where the start and end characters are the same
4153//     cx.set_state("aˇ");
4154//     cx.update_editor(|view, cx| view.handle_input("\"", cx));
4155//     cx.assert_editor_state("a\"ˇ\"");
4156//     cx.update_editor(|view, cx| view.handle_input("\"", cx));
4157//     cx.assert_editor_state("a\"\"ˇ");
4158// }
4159
4160// #[gpui::test]
4161// async fn test_autoclose_with_embedded_language(cx: &mut gpui::TestAppContext) {
4162//     init_test(cx, |_| {});
4163
4164//     let mut cx = EditorTestContext::new(cx).await;
4165
4166//     let html_language = Arc::new(
4167//         Language::new(
4168//             LanguageConfig {
4169//                 name: "HTML".into(),
4170//                 brackets: BracketPairConfig {
4171//                     pairs: vec![
4172//                         BracketPair {
4173//                             start: "<".into(),
4174//                             end: ">".into(),
4175//                             close: true,
4176//                             ..Default::default()
4177//                         },
4178//                         BracketPair {
4179//                             start: "{".into(),
4180//                             end: "}".into(),
4181//                             close: true,
4182//                             ..Default::default()
4183//                         },
4184//                         BracketPair {
4185//                             start: "(".into(),
4186//                             end: ")".into(),
4187//                             close: true,
4188//                             ..Default::default()
4189//                         },
4190//                     ],
4191//                     ..Default::default()
4192//                 },
4193//                 autoclose_before: "})]>".into(),
4194//                 ..Default::default()
4195//             },
4196//             Some(tree_sitter_html::language()),
4197//         )
4198//         .with_injection_query(
4199//             r#"
4200//             (script_element
4201//                 (raw_text) @content
4202//                 (#set! "language" "javascript"))
4203//             "#,
4204//         )
4205//         .unwrap(),
4206//     );
4207
4208//     let javascript_language = Arc::new(Language::new(
4209//         LanguageConfig {
4210//             name: "JavaScript".into(),
4211//             brackets: BracketPairConfig {
4212//                 pairs: vec![
4213//                     BracketPair {
4214//                         start: "/*".into(),
4215//                         end: " */".into(),
4216//                         close: true,
4217//                         ..Default::default()
4218//                     },
4219//                     BracketPair {
4220//                         start: "{".into(),
4221//                         end: "}".into(),
4222//                         close: true,
4223//                         ..Default::default()
4224//                     },
4225//                     BracketPair {
4226//                         start: "(".into(),
4227//                         end: ")".into(),
4228//                         close: true,
4229//                         ..Default::default()
4230//                     },
4231//                 ],
4232//                 ..Default::default()
4233//             },
4234//             autoclose_before: "})]>".into(),
4235//             ..Default::default()
4236//         },
4237//         Some(tree_sitter_typescript::language_tsx()),
4238//     ));
4239
4240//     let registry = Arc::new(LanguageRegistry::test());
4241//     registry.add(html_language.clone());
4242//     registry.add(javascript_language.clone());
4243
4244//     cx.update_buffer(|buffer, cx| {
4245//         buffer.set_language_registry(registry);
4246//         buffer.set_language(Some(html_language), cx);
4247//     });
4248
4249//     cx.set_state(
4250//         &r#"
4251//             <body>ˇ
4252//                 <script>
4253//                     var x = 1;ˇ
4254//                 </script>
4255//             </body>ˇ
4256//         "#
4257//         .unindent(),
4258//     );
4259
4260//     // Precondition: different languages are active at different locations.
4261//     cx.update_editor(|editor, cx| {
4262//         let snapshot = editor.snapshot(cx);
4263//         let cursors = editor.selections.ranges::<usize>(cx);
4264//         let languages = cursors
4265//             .iter()
4266//             .map(|c| snapshot.language_at(c.start).unwrap().name())
4267//             .collect::<Vec<_>>();
4268//         assert_eq!(
4269//             languages,
4270//             &["HTML".into(), "JavaScript".into(), "HTML".into()]
4271//         );
4272//     });
4273
4274//     // Angle brackets autoclose in HTML, but not JavaScript.
4275//     cx.update_editor(|editor, cx| {
4276//         editor.handle_input("<", cx);
4277//         editor.handle_input("a", cx);
4278//     });
4279//     cx.assert_editor_state(
4280//         &r#"
4281//             <body><aˇ>
4282//                 <script>
4283//                     var x = 1;<aˇ
4284//                 </script>
4285//             </body><aˇ>
4286//         "#
4287//         .unindent(),
4288//     );
4289
4290//     // Curly braces and parens autoclose in both HTML and JavaScript.
4291//     cx.update_editor(|editor, cx| {
4292//         editor.handle_input(" b=", cx);
4293//         editor.handle_input("{", cx);
4294//         editor.handle_input("c", cx);
4295//         editor.handle_input("(", cx);
4296//     });
4297//     cx.assert_editor_state(
4298//         &r#"
4299//             <body><a b={c(ˇ)}>
4300//                 <script>
4301//                     var x = 1;<a b={c(ˇ)}
4302//                 </script>
4303//             </body><a b={c(ˇ)}>
4304//         "#
4305//         .unindent(),
4306//     );
4307
4308//     // Brackets that were already autoclosed are skipped.
4309//     cx.update_editor(|editor, cx| {
4310//         editor.handle_input(")", cx);
4311//         editor.handle_input("d", cx);
4312//         editor.handle_input("}", cx);
4313//     });
4314//     cx.assert_editor_state(
4315//         &r#"
4316//             <body><a b={c()d}ˇ>
4317//                 <script>
4318//                     var x = 1;<a b={c()d}ˇ
4319//                 </script>
4320//             </body><a b={c()d}ˇ>
4321//         "#
4322//         .unindent(),
4323//     );
4324//     cx.update_editor(|editor, cx| {
4325//         editor.handle_input(">", cx);
4326//     });
4327//     cx.assert_editor_state(
4328//         &r#"
4329//             <body><a b={c()d}>ˇ
4330//                 <script>
4331//                     var x = 1;<a b={c()d}>ˇ
4332//                 </script>
4333//             </body><a b={c()d}>ˇ
4334//         "#
4335//         .unindent(),
4336//     );
4337
4338//     // Reset
4339//     cx.set_state(
4340//         &r#"
4341//             <body>ˇ
4342//                 <script>
4343//                     var x = 1;ˇ
4344//                 </script>
4345//             </body>ˇ
4346//         "#
4347//         .unindent(),
4348//     );
4349
4350//     cx.update_editor(|editor, cx| {
4351//         editor.handle_input("<", cx);
4352//     });
4353//     cx.assert_editor_state(
4354//         &r#"
4355//             <body><ˇ>
4356//                 <script>
4357//                     var x = 1;<ˇ
4358//                 </script>
4359//             </body><ˇ>
4360//         "#
4361//         .unindent(),
4362//     );
4363
4364//     // When backspacing, the closing angle brackets are removed.
4365//     cx.update_editor(|editor, cx| {
4366//         editor.backspace(&Backspace, cx);
4367//     });
4368//     cx.assert_editor_state(
4369//         &r#"
4370//             <body>ˇ
4371//                 <script>
4372//                     var x = 1;ˇ
4373//                 </script>
4374//             </body>ˇ
4375//         "#
4376//         .unindent(),
4377//     );
4378
4379//     // Block comments autoclose in JavaScript, but not HTML.
4380//     cx.update_editor(|editor, cx| {
4381//         editor.handle_input("/", cx);
4382//         editor.handle_input("*", cx);
4383//     });
4384//     cx.assert_editor_state(
4385//         &r#"
4386//             <body>/*ˇ
4387//                 <script>
4388//                     var x = 1;/*ˇ */
4389//                 </script>
4390//             </body>/*ˇ
4391//         "#
4392//         .unindent(),
4393//     );
4394// }
4395
4396// #[gpui::test]
4397// async fn test_autoclose_with_overrides(cx: &mut gpui::TestAppContext) {
4398//     init_test(cx, |_| {});
4399
4400//     let mut cx = EditorTestContext::new(cx).await;
4401
4402//     let rust_language = Arc::new(
4403//         Language::new(
4404//             LanguageConfig {
4405//                 name: "Rust".into(),
4406//                 brackets: serde_json::from_value(json!([
4407//                     { "start": "{", "end": "}", "close": true, "newline": true },
4408//                     { "start": "\"", "end": "\"", "close": true, "newline": false, "not_in": ["string"] },
4409//                 ]))
4410//                 .unwrap(),
4411//                 autoclose_before: "})]>".into(),
4412//                 ..Default::default()
4413//             },
4414//             Some(tree_sitter_rust::language()),
4415//         )
4416//         .with_override_query("(string_literal) @string")
4417//         .unwrap(),
4418//     );
4419
4420//     let registry = Arc::new(LanguageRegistry::test());
4421//     registry.add(rust_language.clone());
4422
4423//     cx.update_buffer(|buffer, cx| {
4424//         buffer.set_language_registry(registry);
4425//         buffer.set_language(Some(rust_language), cx);
4426//     });
4427
4428//     cx.set_state(
4429//         &r#"
4430//             let x = ˇ
4431//         "#
4432//         .unindent(),
4433//     );
4434
4435//     // Inserting a quotation mark. A closing quotation mark is automatically inserted.
4436//     cx.update_editor(|editor, cx| {
4437//         editor.handle_input("\"", cx);
4438//     });
4439//     cx.assert_editor_state(
4440//         &r#"
4441//             let x = "ˇ"
4442//         "#
4443//         .unindent(),
4444//     );
4445
4446//     // Inserting another quotation mark. The cursor moves across the existing
4447//     // automatically-inserted quotation mark.
4448//     cx.update_editor(|editor, cx| {
4449//         editor.handle_input("\"", cx);
4450//     });
4451//     cx.assert_editor_state(
4452//         &r#"
4453//             let x = ""ˇ
4454//         "#
4455//         .unindent(),
4456//     );
4457
4458//     // Reset
4459//     cx.set_state(
4460//         &r#"
4461//             let x = ˇ
4462//         "#
4463//         .unindent(),
4464//     );
4465
4466//     // Inserting a quotation mark inside of a string. A second quotation mark is not inserted.
4467//     cx.update_editor(|editor, cx| {
4468//         editor.handle_input("\"", cx);
4469//         editor.handle_input(" ", cx);
4470//         editor.move_left(&Default::default(), cx);
4471//         editor.handle_input("\\", cx);
4472//         editor.handle_input("\"", cx);
4473//     });
4474//     cx.assert_editor_state(
4475//         &r#"
4476//             let x = "\"ˇ "
4477//         "#
4478//         .unindent(),
4479//     );
4480
4481//     // Inserting a closing quotation mark at the position of an automatically-inserted quotation
4482//     // mark. Nothing is inserted.
4483//     cx.update_editor(|editor, cx| {
4484//         editor.move_right(&Default::default(), cx);
4485//         editor.handle_input("\"", cx);
4486//     });
4487//     cx.assert_editor_state(
4488//         &r#"
4489//             let x = "\" "ˇ
4490//         "#
4491//         .unindent(),
4492//     );
4493// }
4494
4495// #[gpui::test]
4496// async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
4497//     init_test(cx, |_| {});
4498
4499//     let language = Arc::new(Language::new(
4500//         LanguageConfig {
4501//             brackets: BracketPairConfig {
4502//                 pairs: vec![
4503//                     BracketPair {
4504//                         start: "{".to_string(),
4505//                         end: "}".to_string(),
4506//                         close: true,
4507//                         newline: true,
4508//                     },
4509//                     BracketPair {
4510//                         start: "/* ".to_string(),
4511//                         end: "*/".to_string(),
4512//                         close: true,
4513//                         ..Default::default()
4514//                     },
4515//                 ],
4516//                 ..Default::default()
4517//             },
4518//             ..Default::default()
4519//         },
4520//         Some(tree_sitter_rust::language()),
4521//     ));
4522
4523//     let text = r#"
4524//         a
4525//         b
4526//         c
4527//     "#
4528//     .unindent();
4529
4530//     let buffer =
4531//         cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx));
4532//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
4533//     let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
4534//     view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
4535//         .await;
4536
4537//     view.update(cx, |view, cx| {
4538//         view.change_selections(None, cx, |s| {
4539//             s.select_display_ranges([
4540//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4541//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4542//                 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
4543//             ])
4544//         });
4545
4546//         view.handle_input("{", cx);
4547//         view.handle_input("{", cx);
4548//         view.handle_input("{", cx);
4549//         assert_eq!(
4550//             view.text(cx),
4551//             "
4552//                 {{{a}}}
4553//                 {{{b}}}
4554//                 {{{c}}}
4555//             "
4556//             .unindent()
4557//         );
4558//         assert_eq!(
4559//             view.selections.display_ranges(cx),
4560//             [
4561//                 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
4562//                 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
4563//                 DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
4564//             ]
4565//         );
4566
4567//         view.undo(&Undo, cx);
4568//         view.undo(&Undo, cx);
4569//         view.undo(&Undo, cx);
4570//         assert_eq!(
4571//             view.text(cx),
4572//             "
4573//                 a
4574//                 b
4575//                 c
4576//             "
4577//             .unindent()
4578//         );
4579//         assert_eq!(
4580//             view.selections.display_ranges(cx),
4581//             [
4582//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4583//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4584//                 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
4585//             ]
4586//         );
4587
4588//         // Ensure inserting the first character of a multi-byte bracket pair
4589//         // doesn't surround the selections with the bracket.
4590//         view.handle_input("/", cx);
4591//         assert_eq!(
4592//             view.text(cx),
4593//             "
4594//                 /
4595//                 /
4596//                 /
4597//             "
4598//             .unindent()
4599//         );
4600//         assert_eq!(
4601//             view.selections.display_ranges(cx),
4602//             [
4603//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4604//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4605//                 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1)
4606//             ]
4607//         );
4608
4609//         view.undo(&Undo, cx);
4610//         assert_eq!(
4611//             view.text(cx),
4612//             "
4613//                 a
4614//                 b
4615//                 c
4616//             "
4617//             .unindent()
4618//         );
4619//         assert_eq!(
4620//             view.selections.display_ranges(cx),
4621//             [
4622//                 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4623//                 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4624//                 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
4625//             ]
4626//         );
4627
4628//         // Ensure inserting the last character of a multi-byte bracket pair
4629//         // doesn't surround the selections with the bracket.
4630//         view.handle_input("*", cx);
4631//         assert_eq!(
4632//             view.text(cx),
4633//             "
4634//                 *
4635//                 *
4636//                 *
4637//             "
4638//             .unindent()
4639//         );
4640//         assert_eq!(
4641//             view.selections.display_ranges(cx),
4642//             [
4643//                 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4644//                 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4645//                 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1)
4646//             ]
4647//         );
4648//     });
4649// }
4650
4651// #[gpui::test]
4652// async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
4653//     init_test(cx, |_| {});
4654
4655//     let language = Arc::new(Language::new(
4656//         LanguageConfig {
4657//             brackets: BracketPairConfig {
4658//                 pairs: vec![BracketPair {
4659//                     start: "{".to_string(),
4660//                     end: "}".to_string(),
4661//                     close: true,
4662//                     newline: true,
4663//                 }],
4664//                 ..Default::default()
4665//             },
4666//             autoclose_before: "}".to_string(),
4667//             ..Default::default()
4668//         },
4669//         Some(tree_sitter_rust::language()),
4670//     ));
4671
4672//     let text = r#"
4673//         a
4674//         b
4675//         c
4676//     "#
4677//     .unindent();
4678
4679//     let buffer =
4680//         cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx));
4681//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
4682//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
4683//     editor
4684//         .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
4685//         .await;
4686
4687//     editor.update(cx, |editor, cx| {
4688//         editor.change_selections(None, cx, |s| {
4689//             s.select_ranges([
4690//                 Point::new(0, 1)..Point::new(0, 1),
4691//                 Point::new(1, 1)..Point::new(1, 1),
4692//                 Point::new(2, 1)..Point::new(2, 1),
4693//             ])
4694//         });
4695
4696//         editor.handle_input("{", cx);
4697//         editor.handle_input("{", cx);
4698//         editor.handle_input("_", cx);
4699//         assert_eq!(
4700//             editor.text(cx),
4701//             "
4702//                 a{{_}}
4703//                 b{{_}}
4704//                 c{{_}}
4705//             "
4706//             .unindent()
4707//         );
4708//         assert_eq!(
4709//             editor.selections.ranges::<Point>(cx),
4710//             [
4711//                 Point::new(0, 4)..Point::new(0, 4),
4712//                 Point::new(1, 4)..Point::new(1, 4),
4713//                 Point::new(2, 4)..Point::new(2, 4)
4714//             ]
4715//         );
4716
4717//         editor.backspace(&Default::default(), cx);
4718//         editor.backspace(&Default::default(), cx);
4719//         assert_eq!(
4720//             editor.text(cx),
4721//             "
4722//                 a{}
4723//                 b{}
4724//                 c{}
4725//             "
4726//             .unindent()
4727//         );
4728//         assert_eq!(
4729//             editor.selections.ranges::<Point>(cx),
4730//             [
4731//                 Point::new(0, 2)..Point::new(0, 2),
4732//                 Point::new(1, 2)..Point::new(1, 2),
4733//                 Point::new(2, 2)..Point::new(2, 2)
4734//             ]
4735//         );
4736
4737//         editor.delete_to_previous_word_start(&Default::default(), cx);
4738//         assert_eq!(
4739//             editor.text(cx),
4740//             "
4741//                 a
4742//                 b
4743//                 c
4744//             "
4745//             .unindent()
4746//         );
4747//         assert_eq!(
4748//             editor.selections.ranges::<Point>(cx),
4749//             [
4750//                 Point::new(0, 1)..Point::new(0, 1),
4751//                 Point::new(1, 1)..Point::new(1, 1),
4752//                 Point::new(2, 1)..Point::new(2, 1)
4753//             ]
4754//         );
4755//     });
4756// }
4757
4758// #[gpui::test]
4759// async fn test_snippets(cx: &mut gpui::TestAppContext) {
4760//     init_test(cx, |_| {});
4761
4762//     let (text, insertion_ranges) = marked_text_ranges(
4763//         indoc! {"
4764//             a.ˇ b
4765//             a.ˇ b
4766//             a.ˇ b
4767//         "},
4768//         false,
4769//     );
4770
4771//     let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
4772//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
4773
4774//     editor.update(cx, |editor, cx| {
4775//         let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
4776
4777//         editor
4778//             .insert_snippet(&insertion_ranges, snippet, cx)
4779//             .unwrap();
4780
4781//         fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text: &str) {
4782//             let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
4783//             assert_eq!(editor.text(cx), expected_text);
4784//             assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
4785//         }
4786
4787//         assert(
4788//             editor,
4789//             cx,
4790//             indoc! {"
4791//                 a.f(«one», two, «three») b
4792//                 a.f(«one», two, «three») b
4793//                 a.f(«one», two, «three») b
4794//             "},
4795//         );
4796
4797//         // Can't move earlier than the first tab stop
4798//         assert!(!editor.move_to_prev_snippet_tabstop(cx));
4799//         assert(
4800//             editor,
4801//             cx,
4802//             indoc! {"
4803//                 a.f(«one», two, «three») b
4804//                 a.f(«one», two, «three») b
4805//                 a.f(«one», two, «three») b
4806//             "},
4807//         );
4808
4809//         assert!(editor.move_to_next_snippet_tabstop(cx));
4810//         assert(
4811//             editor,
4812//             cx,
4813//             indoc! {"
4814//                 a.f(one, «two», three) b
4815//                 a.f(one, «two», three) b
4816//                 a.f(one, «two», three) b
4817//             "},
4818//         );
4819
4820//         editor.move_to_prev_snippet_tabstop(cx);
4821//         assert(
4822//             editor,
4823//             cx,
4824//             indoc! {"
4825//                 a.f(«one», two, «three») b
4826//                 a.f(«one», two, «three») b
4827//                 a.f(«one», two, «three») b
4828//             "},
4829//         );
4830
4831//         assert!(editor.move_to_next_snippet_tabstop(cx));
4832//         assert(
4833//             editor,
4834//             cx,
4835//             indoc! {"
4836//                 a.f(one, «two», three) b
4837//                 a.f(one, «two», three) b
4838//                 a.f(one, «two», three) b
4839//             "},
4840//         );
4841//         assert!(editor.move_to_next_snippet_tabstop(cx));
4842//         assert(
4843//             editor,
4844//             cx,
4845//             indoc! {"
4846//                 a.f(one, two, three)ˇ b
4847//                 a.f(one, two, three)ˇ b
4848//                 a.f(one, two, three)ˇ b
4849//             "},
4850//         );
4851
4852//         // As soon as the last tab stop is reached, snippet state is gone
4853//         editor.move_to_prev_snippet_tabstop(cx);
4854//         assert(
4855//             editor,
4856//             cx,
4857//             indoc! {"
4858//                 a.f(one, two, three)ˇ b
4859//                 a.f(one, two, three)ˇ b
4860//                 a.f(one, two, three)ˇ b
4861//             "},
4862//         );
4863//     });
4864// }
4865
4866// #[gpui::test]
4867// async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
4868//     init_test(cx, |_| {});
4869
4870//     let mut language = Language::new(
4871//         LanguageConfig {
4872//             name: "Rust".into(),
4873//             path_suffixes: vec!["rs".to_string()],
4874//             ..Default::default()
4875//         },
4876//         Some(tree_sitter_rust::language()),
4877//     );
4878//     let mut fake_servers = language
4879//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
4880//             capabilities: lsp::ServerCapabilities {
4881//                 document_formatting_provider: Some(lsp::OneOf::Left(true)),
4882//                 ..Default::default()
4883//             },
4884//             ..Default::default()
4885//         }))
4886//         .await;
4887
4888//     let fs = FakeFs::new(cx.background());
4889//     fs.insert_file("/file.rs", Default::default()).await;
4890
4891//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
4892//     project.update(cx, |project, _| project.languages().add(Arc::new(language)));
4893//     let buffer = project
4894//         .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
4895//         .await
4896//         .unwrap();
4897
4898//     cx.foreground().start_waiting();
4899//     let fake_server = fake_servers.next().await.unwrap();
4900
4901//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
4902//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
4903//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
4904//     assert!(cx.read(|cx| editor.is_dirty(cx)));
4905
4906//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
4907//     fake_server
4908//         .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
4909//             assert_eq!(
4910//                 params.text_document.uri,
4911//                 lsp::Url::from_file_path("/file.rs").unwrap()
4912//             );
4913//             assert_eq!(params.options.tab_size, 4);
4914//             Ok(Some(vec![lsp::TextEdit::new(
4915//                 lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
4916//                 ", ".to_string(),
4917//             )]))
4918//         })
4919//         .next()
4920//         .await;
4921//     cx.foreground().start_waiting();
4922//     save.await.unwrap();
4923//     assert_eq!(
4924//         editor.read_with(cx, |editor, cx| editor.text(cx)),
4925//         "one, two\nthree\n"
4926//     );
4927//     assert!(!cx.read(|cx| editor.is_dirty(cx)));
4928
4929//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
4930//     assert!(cx.read(|cx| editor.is_dirty(cx)));
4931
4932//     // Ensure we can still save even if formatting hangs.
4933//     fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
4934//         assert_eq!(
4935//             params.text_document.uri,
4936//             lsp::Url::from_file_path("/file.rs").unwrap()
4937//         );
4938//         futures::future::pending::<()>().await;
4939//         unreachable!()
4940//     });
4941//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
4942//     cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
4943//     cx.foreground().start_waiting();
4944//     save.await.unwrap();
4945//     assert_eq!(
4946//         editor.read_with(cx, |editor, cx| editor.text(cx)),
4947//         "one\ntwo\nthree\n"
4948//     );
4949//     assert!(!cx.read(|cx| editor.is_dirty(cx)));
4950
4951//     // Set rust language override and assert overridden tabsize is sent to language server
4952//     update_test_language_settings(cx, |settings| {
4953//         settings.languages.insert(
4954//             "Rust".into(),
4955//             LanguageSettingsContent {
4956//                 tab_size: NonZeroU32::new(8),
4957//                 ..Default::default()
4958//             },
4959//         );
4960//     });
4961
4962//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
4963//     fake_server
4964//         .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
4965//             assert_eq!(
4966//                 params.text_document.uri,
4967//                 lsp::Url::from_file_path("/file.rs").unwrap()
4968//             );
4969//             assert_eq!(params.options.tab_size, 8);
4970//             Ok(Some(vec![]))
4971//         })
4972//         .next()
4973//         .await;
4974//     cx.foreground().start_waiting();
4975//     save.await.unwrap();
4976// }
4977
4978// #[gpui::test]
4979// async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
4980//     init_test(cx, |_| {});
4981
4982//     let mut language = Language::new(
4983//         LanguageConfig {
4984//             name: "Rust".into(),
4985//             path_suffixes: vec!["rs".to_string()],
4986//             ..Default::default()
4987//         },
4988//         Some(tree_sitter_rust::language()),
4989//     );
4990//     let mut fake_servers = language
4991//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
4992//             capabilities: lsp::ServerCapabilities {
4993//                 document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
4994//                 ..Default::default()
4995//             },
4996//             ..Default::default()
4997//         }))
4998//         .await;
4999
5000//     let fs = FakeFs::new(cx.background());
5001//     fs.insert_file("/file.rs", Default::default()).await;
5002
5003//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
5004//     project.update(cx, |project, _| project.languages().add(Arc::new(language)));
5005//     let buffer = project
5006//         .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
5007//         .await
5008//         .unwrap();
5009
5010//     cx.foreground().start_waiting();
5011//     let fake_server = fake_servers.next().await.unwrap();
5012
5013//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5014//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
5015//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
5016//     assert!(cx.read(|cx| editor.is_dirty(cx)));
5017
5018//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
5019//     fake_server
5020//         .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
5021//             assert_eq!(
5022//                 params.text_document.uri,
5023//                 lsp::Url::from_file_path("/file.rs").unwrap()
5024//             );
5025//             assert_eq!(params.options.tab_size, 4);
5026//             Ok(Some(vec![lsp::TextEdit::new(
5027//                 lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
5028//                 ", ".to_string(),
5029//             )]))
5030//         })
5031//         .next()
5032//         .await;
5033//     cx.foreground().start_waiting();
5034//     save.await.unwrap();
5035//     assert_eq!(
5036//         editor.read_with(cx, |editor, cx| editor.text(cx)),
5037//         "one, two\nthree\n"
5038//     );
5039//     assert!(!cx.read(|cx| editor.is_dirty(cx)));
5040
5041//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
5042//     assert!(cx.read(|cx| editor.is_dirty(cx)));
5043
5044//     // Ensure we can still save even if formatting hangs.
5045//     fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
5046//         move |params, _| async move {
5047//             assert_eq!(
5048//                 params.text_document.uri,
5049//                 lsp::Url::from_file_path("/file.rs").unwrap()
5050//             );
5051//             futures::future::pending::<()>().await;
5052//             unreachable!()
5053//         },
5054//     );
5055//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
5056//     cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
5057//     cx.foreground().start_waiting();
5058//     save.await.unwrap();
5059//     assert_eq!(
5060//         editor.read_with(cx, |editor, cx| editor.text(cx)),
5061//         "one\ntwo\nthree\n"
5062//     );
5063//     assert!(!cx.read(|cx| editor.is_dirty(cx)));
5064
5065//     // Set rust language override and assert overridden tabsize is sent to language server
5066//     update_test_language_settings(cx, |settings| {
5067//         settings.languages.insert(
5068//             "Rust".into(),
5069//             LanguageSettingsContent {
5070//                 tab_size: NonZeroU32::new(8),
5071//                 ..Default::default()
5072//             },
5073//         );
5074//     });
5075
5076//     let save = editor.update(cx, |editor, cx| editor.save(project.clone(), cx));
5077//     fake_server
5078//         .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
5079//             assert_eq!(
5080//                 params.text_document.uri,
5081//                 lsp::Url::from_file_path("/file.rs").unwrap()
5082//             );
5083//             assert_eq!(params.options.tab_size, 8);
5084//             Ok(Some(vec![]))
5085//         })
5086//         .next()
5087//         .await;
5088//     cx.foreground().start_waiting();
5089//     save.await.unwrap();
5090// }
5091
5092// #[gpui::test]
5093// async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
5094//     init_test(cx, |settings| {
5095//         settings.defaults.formatter = Some(language_settings::Formatter::LanguageServer)
5096//     });
5097
5098//     let mut language = Language::new(
5099//         LanguageConfig {
5100//             name: "Rust".into(),
5101//             path_suffixes: vec!["rs".to_string()],
5102//             // Enable Prettier formatting for the same buffer, and ensure
5103//             // LSP is called instead of Prettier.
5104//             prettier_parser_name: Some("test_parser".to_string()),
5105//             ..Default::default()
5106//         },
5107//         Some(tree_sitter_rust::language()),
5108//     );
5109//     let mut fake_servers = language
5110//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
5111//             capabilities: lsp::ServerCapabilities {
5112//                 document_formatting_provider: Some(lsp::OneOf::Left(true)),
5113//                 ..Default::default()
5114//             },
5115//             ..Default::default()
5116//         }))
5117//         .await;
5118
5119//     let fs = FakeFs::new(cx.background());
5120//     fs.insert_file("/file.rs", Default::default()).await;
5121
5122//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
5123//     project.update(cx, |project, _| {
5124//         project.languages().add(Arc::new(language));
5125//     });
5126//     let buffer = project
5127//         .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
5128//         .await
5129//         .unwrap();
5130
5131//     cx.foreground().start_waiting();
5132//     let fake_server = fake_servers.next().await.unwrap();
5133
5134//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5135//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
5136//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
5137
5138//     let format = editor.update(cx, |editor, cx| {
5139//         editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
5140//     });
5141//     fake_server
5142//         .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
5143//             assert_eq!(
5144//                 params.text_document.uri,
5145//                 lsp::Url::from_file_path("/file.rs").unwrap()
5146//             );
5147//             assert_eq!(params.options.tab_size, 4);
5148//             Ok(Some(vec![lsp::TextEdit::new(
5149//                 lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
5150//                 ", ".to_string(),
5151//             )]))
5152//         })
5153//         .next()
5154//         .await;
5155//     cx.foreground().start_waiting();
5156//     format.await.unwrap();
5157//     assert_eq!(
5158//         editor.read_with(cx, |editor, cx| editor.text(cx)),
5159//         "one, two\nthree\n"
5160//     );
5161
5162//     editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
5163//     // Ensure we don't lock if formatting hangs.
5164//     fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
5165//         assert_eq!(
5166//             params.text_document.uri,
5167//             lsp::Url::from_file_path("/file.rs").unwrap()
5168//         );
5169//         futures::future::pending::<()>().await;
5170//         unreachable!()
5171//     });
5172//     let format = editor.update(cx, |editor, cx| {
5173//         editor.perform_format(project, FormatTrigger::Manual, cx)
5174//     });
5175//     cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
5176//     cx.foreground().start_waiting();
5177//     format.await.unwrap();
5178//     assert_eq!(
5179//         editor.read_with(cx, |editor, cx| editor.text(cx)),
5180//         "one\ntwo\nthree\n"
5181//     );
5182// }
5183
5184// #[gpui::test]
5185// async fn test_concurrent_format_requests(cx: &mut gpui::TestAppContext) {
5186//     init_test(cx, |_| {});
5187
5188//     let mut cx = EditorLspTestContext::new_rust(
5189//         lsp::ServerCapabilities {
5190//             document_formatting_provider: Some(lsp::OneOf::Left(true)),
5191//             ..Default::default()
5192//         },
5193//         cx,
5194//     )
5195//     .await;
5196
5197//     cx.set_state(indoc! {"
5198//         one.twoˇ
5199//     "});
5200
5201//     // The format request takes a long time. When it completes, it inserts
5202//     // a newline and an indent before the `.`
5203//     cx.lsp
5204//         .handle_request::<lsp::request::Formatting, _, _>(move |_, cx| {
5205//             let executor = cx.background();
5206//             async move {
5207//                 executor.timer(Duration::from_millis(100)).await;
5208//                 Ok(Some(vec![lsp::TextEdit {
5209//                     range: lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(0, 3)),
5210//                     new_text: "\n    ".into(),
5211//                 }]))
5212//             }
5213//         });
5214
5215//     // Submit a format request.
5216//     let format_1 = cx
5217//         .update_editor(|editor, cx| editor.format(&Format, cx))
5218//         .unwrap();
5219//     cx.foreground().run_until_parked();
5220
5221//     // Submit a second format request.
5222//     let format_2 = cx
5223//         .update_editor(|editor, cx| editor.format(&Format, cx))
5224//         .unwrap();
5225//     cx.foreground().run_until_parked();
5226
5227//     // Wait for both format requests to complete
5228//     cx.foreground().advance_clock(Duration::from_millis(200));
5229//     cx.foreground().start_waiting();
5230//     format_1.await.unwrap();
5231//     cx.foreground().start_waiting();
5232//     format_2.await.unwrap();
5233
5234//     // The formatting edits only happens once.
5235//     cx.assert_editor_state(indoc! {"
5236//         one
5237//             .twoˇ
5238//     "});
5239// }
5240
5241// #[gpui::test]
5242// async fn test_strip_whitespace_and_format_via_lsp(cx: &mut gpui::TestAppContext) {
5243//     init_test(cx, |settings| {
5244//         settings.defaults.formatter = Some(language_settings::Formatter::Auto)
5245//     });
5246
5247//     let mut cx = EditorLspTestContext::new_rust(
5248//         lsp::ServerCapabilities {
5249//             document_formatting_provider: Some(lsp::OneOf::Left(true)),
5250//             ..Default::default()
5251//         },
5252//         cx,
5253//     )
5254//     .await;
5255
5256//     // Set up a buffer white some trailing whitespace and no trailing newline.
5257//     cx.set_state(
5258//         &[
5259//             "one ",   //
5260//             "twoˇ",   //
5261//             "three ", //
5262//             "four",   //
5263//         ]
5264//         .join("\n"),
5265//     );
5266
5267//     // Submit a format request.
5268//     let format = cx
5269//         .update_editor(|editor, cx| editor.format(&Format, cx))
5270//         .unwrap();
5271
5272//     // Record which buffer changes have been sent to the language server
5273//     let buffer_changes = Arc::new(Mutex::new(Vec::new()));
5274//     cx.lsp
5275//         .handle_notification::<lsp::notification::DidChangeTextDocument, _>({
5276//             let buffer_changes = buffer_changes.clone();
5277//             move |params, _| {
5278//                 buffer_changes.lock().extend(
5279//                     params
5280//                         .content_changes
5281//                         .into_iter()
5282//                         .map(|e| (e.range.unwrap(), e.text)),
5283//                 );
5284//             }
5285//         });
5286
5287//     // Handle formatting requests to the language server.
5288//     cx.lsp.handle_request::<lsp::request::Formatting, _, _>({
5289//         let buffer_changes = buffer_changes.clone();
5290//         move |_, _| {
5291//             // When formatting is requested, trailing whitespace has already been stripped,
5292//             // and the trailing newline has already been added.
5293//             assert_eq!(
5294//                 &buffer_changes.lock()[1..],
5295//                 &[
5296//                     (
5297//                         lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(0, 4)),
5298//                         "".into()
5299//                     ),
5300//                     (
5301//                         lsp::Range::new(lsp::Position::new(2, 5), lsp::Position::new(2, 6)),
5302//                         "".into()
5303//                     ),
5304//                     (
5305//                         lsp::Range::new(lsp::Position::new(3, 4), lsp::Position::new(3, 4)),
5306//                         "\n".into()
5307//                     ),
5308//                 ]
5309//             );
5310
5311//             // Insert blank lines between each line of the buffer.
5312//             async move {
5313//                 Ok(Some(vec![
5314//                     lsp::TextEdit {
5315//                         range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 0)),
5316//                         new_text: "\n".into(),
5317//                     },
5318//                     lsp::TextEdit {
5319//                         range: lsp::Range::new(lsp::Position::new(2, 0), lsp::Position::new(2, 0)),
5320//                         new_text: "\n".into(),
5321//                     },
5322//                 ]))
5323//             }
5324//         }
5325//     });
5326
5327//     // After formatting the buffer, the trailing whitespace is stripped,
5328//     // a newline is appended, and the edits provided by the language server
5329//     // have been applied.
5330//     format.await.unwrap();
5331//     cx.assert_editor_state(
5332//         &[
5333//             "one",   //
5334//             "",      //
5335//             "twoˇ",  //
5336//             "",      //
5337//             "three", //
5338//             "four",  //
5339//             "",      //
5340//         ]
5341//         .join("\n"),
5342//     );
5343
5344//     // Undoing the formatting undoes the trailing whitespace removal, the
5345//     // trailing newline, and the LSP edits.
5346//     cx.update_buffer(|buffer, cx| buffer.undo(cx));
5347//     cx.assert_editor_state(
5348//         &[
5349//             "one ",   //
5350//             "twoˇ",   //
5351//             "three ", //
5352//             "four",   //
5353//         ]
5354//         .join("\n"),
5355//     );
5356// }
5357
5358// #[gpui::test]
5359// async fn test_completion(cx: &mut gpui::TestAppContext) {
5360//     init_test(cx, |_| {});
5361
5362//     let mut cx = EditorLspTestContext::new_rust(
5363//         lsp::ServerCapabilities {
5364//             completion_provider: Some(lsp::CompletionOptions {
5365//                 trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
5366//                 resolve_provider: Some(true),
5367//                 ..Default::default()
5368//             }),
5369//             ..Default::default()
5370//         },
5371//         cx,
5372//     )
5373//     .await;
5374
5375//     cx.set_state(indoc! {"
5376//         oneˇ
5377//         two
5378//         three
5379//     "});
5380//     cx.simulate_keystroke(".");
5381//     handle_completion_request(
5382//         &mut cx,
5383//         indoc! {"
5384//             one.|<>
5385//             two
5386//             three
5387//         "},
5388//         vec!["first_completion", "second_completion"],
5389//     )
5390//     .await;
5391//     cx.condition(|editor, _| editor.context_menu_visible())
5392//         .await;
5393//     let apply_additional_edits = cx.update_editor(|editor, cx| {
5394//         editor.context_menu_next(&Default::default(), cx);
5395//         editor
5396//             .confirm_completion(&ConfirmCompletion::default(), cx)
5397//             .unwrap()
5398//     });
5399//     cx.assert_editor_state(indoc! {"
5400//         one.second_completionˇ
5401//         two
5402//         three
5403//     "});
5404
5405//     handle_resolve_completion_request(
5406//         &mut cx,
5407//         Some(vec![
5408//             (
5409//                 //This overlaps with the primary completion edit which is
5410//                 //misbehavior from the LSP spec, test that we filter it out
5411//                 indoc! {"
5412//                     one.second_ˇcompletion
5413//                     two
5414//                     threeˇ
5415//                 "},
5416//                 "overlapping additional edit",
5417//             ),
5418//             (
5419//                 indoc! {"
5420//                     one.second_completion
5421//                     two
5422//                     threeˇ
5423//                 "},
5424//                 "\nadditional edit",
5425//             ),
5426//         ]),
5427//     )
5428//     .await;
5429//     apply_additional_edits.await.unwrap();
5430//     cx.assert_editor_state(indoc! {"
5431//         one.second_completionˇ
5432//         two
5433//         three
5434//         additional edit
5435//     "});
5436
5437//     cx.set_state(indoc! {"
5438//         one.second_completion
5439//         twoˇ
5440//         threeˇ
5441//         additional edit
5442//     "});
5443//     cx.simulate_keystroke(" ");
5444//     assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
5445//     cx.simulate_keystroke("s");
5446//     assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
5447
5448//     cx.assert_editor_state(indoc! {"
5449//         one.second_completion
5450//         two sˇ
5451//         three sˇ
5452//         additional edit
5453//     "});
5454//     handle_completion_request(
5455//         &mut cx,
5456//         indoc! {"
5457//             one.second_completion
5458//             two s
5459//             three <s|>
5460//             additional edit
5461//         "},
5462//         vec!["fourth_completion", "fifth_completion", "sixth_completion"],
5463//     )
5464//     .await;
5465//     cx.condition(|editor, _| editor.context_menu_visible())
5466//         .await;
5467
5468//     cx.simulate_keystroke("i");
5469
5470//     handle_completion_request(
5471//         &mut cx,
5472//         indoc! {"
5473//             one.second_completion
5474//             two si
5475//             three <si|>
5476//             additional edit
5477//         "},
5478//         vec!["fourth_completion", "fifth_completion", "sixth_completion"],
5479//     )
5480//     .await;
5481//     cx.condition(|editor, _| editor.context_menu_visible())
5482//         .await;
5483
5484//     let apply_additional_edits = cx.update_editor(|editor, cx| {
5485//         editor
5486//             .confirm_completion(&ConfirmCompletion::default(), cx)
5487//             .unwrap()
5488//     });
5489//     cx.assert_editor_state(indoc! {"
5490//         one.second_completion
5491//         two sixth_completionˇ
5492//         three sixth_completionˇ
5493//         additional edit
5494//     "});
5495
5496//     handle_resolve_completion_request(&mut cx, None).await;
5497//     apply_additional_edits.await.unwrap();
5498
5499//     cx.update(|cx| {
5500//         cx.update_global::<SettingsStore, _, _>(|settings, cx| {
5501//             settings.update_user_settings::<EditorSettings>(cx, |settings| {
5502//                 settings.show_completions_on_input = Some(false);
5503//             });
5504//         })
5505//     });
5506//     cx.set_state("editorˇ");
5507//     cx.simulate_keystroke(".");
5508//     assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
5509//     cx.simulate_keystroke("c");
5510//     cx.simulate_keystroke("l");
5511//     cx.simulate_keystroke("o");
5512//     cx.assert_editor_state("editor.cloˇ");
5513//     assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
5514//     cx.update_editor(|editor, cx| {
5515//         editor.show_completions(&ShowCompletions, cx);
5516//     });
5517//     handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
5518//     cx.condition(|editor, _| editor.context_menu_visible())
5519//         .await;
5520//     let apply_additional_edits = cx.update_editor(|editor, cx| {
5521//         editor
5522//             .confirm_completion(&ConfirmCompletion::default(), cx)
5523//             .unwrap()
5524//     });
5525//     cx.assert_editor_state("editor.closeˇ");
5526//     handle_resolve_completion_request(&mut cx, None).await;
5527//     apply_additional_edits.await.unwrap();
5528// }
5529
5530// #[gpui::test]
5531// async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
5532//     init_test(cx, |_| {});
5533//     let mut cx = EditorTestContext::new(cx).await;
5534//     let language = Arc::new(Language::new(
5535//         LanguageConfig {
5536//             line_comment: Some("// ".into()),
5537//             ..Default::default()
5538//         },
5539//         Some(tree_sitter_rust::language()),
5540//     ));
5541//     cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
5542
5543//     // If multiple selections intersect a line, the line is only toggled once.
5544//     cx.set_state(indoc! {"
5545//         fn a() {
5546//             «//b();
5547//             ˇ»// «c();
5548//             //ˇ»  d();
5549//         }
5550//     "});
5551
5552//     cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
5553
5554//     cx.assert_editor_state(indoc! {"
5555//         fn a() {
5556//             «b();
5557//             c();
5558//             ˇ» d();
5559//         }
5560//     "});
5561
5562//     // The comment prefix is inserted at the same column for every line in a
5563//     // selection.
5564//     cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
5565
5566//     cx.assert_editor_state(indoc! {"
5567//         fn a() {
5568//             // «b();
5569//             // c();
5570//             ˇ»//  d();
5571//         }
5572//     "});
5573
5574//     // If a selection ends at the beginning of a line, that line is not toggled.
5575//     cx.set_selections_state(indoc! {"
5576//         fn a() {
5577//             // b();
5578//             «// c();
5579//         ˇ»    //  d();
5580//         }
5581//     "});
5582
5583//     cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
5584
5585//     cx.assert_editor_state(indoc! {"
5586//         fn a() {
5587//             // b();
5588//             «c();
5589//         ˇ»    //  d();
5590//         }
5591//     "});
5592
5593//     // If a selection span a single line and is empty, the line is toggled.
5594//     cx.set_state(indoc! {"
5595//         fn a() {
5596//             a();
5597//             b();
5598//         ˇ
5599//         }
5600//     "});
5601
5602//     cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
5603
5604//     cx.assert_editor_state(indoc! {"
5605//         fn a() {
5606//             a();
5607//             b();
5608//         //•ˇ
5609//         }
5610//     "});
5611
5612//     // If a selection span multiple lines, empty lines are not toggled.
5613//     cx.set_state(indoc! {"
5614//         fn a() {
5615//             «a();
5616
5617//             c();ˇ»
5618//         }
5619//     "});
5620
5621//     cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
5622
5623//     cx.assert_editor_state(indoc! {"
5624//         fn a() {
5625//             // «a();
5626
5627//             // c();ˇ»
5628//         }
5629//     "});
5630// }
5631
5632// #[gpui::test]
5633// async fn test_advance_downward_on_toggle_comment(cx: &mut gpui::TestAppContext) {
5634//     init_test(cx, |_| {});
5635
5636//     let language = Arc::new(Language::new(
5637//         LanguageConfig {
5638//             line_comment: Some("// ".into()),
5639//             ..Default::default()
5640//         },
5641//         Some(tree_sitter_rust::language()),
5642//     ));
5643
5644//     let registry = Arc::new(LanguageRegistry::test());
5645//     registry.add(language.clone());
5646
5647//     let mut cx = EditorTestContext::new(cx).await;
5648//     cx.update_buffer(|buffer, cx| {
5649//         buffer.set_language_registry(registry);
5650//         buffer.set_language(Some(language), cx);
5651//     });
5652
5653//     let toggle_comments = &ToggleComments {
5654//         advance_downwards: true,
5655//     };
5656
5657//     // Single cursor on one line -> advance
5658//     // Cursor moves horizontally 3 characters as well on non-blank line
5659//     cx.set_state(indoc!(
5660//         "fn a() {
5661//              ˇdog();
5662//              cat();
5663//         }"
5664//     ));
5665//     cx.update_editor(|editor, cx| {
5666//         editor.toggle_comments(toggle_comments, cx);
5667//     });
5668//     cx.assert_editor_state(indoc!(
5669//         "fn a() {
5670//              // dog();
5671//              catˇ();
5672//         }"
5673//     ));
5674
5675//     // Single selection on one line -> don't advance
5676//     cx.set_state(indoc!(
5677//         "fn a() {
5678//              «dog()ˇ»;
5679//              cat();
5680//         }"
5681//     ));
5682//     cx.update_editor(|editor, cx| {
5683//         editor.toggle_comments(toggle_comments, cx);
5684//     });
5685//     cx.assert_editor_state(indoc!(
5686//         "fn a() {
5687//              // «dog()ˇ»;
5688//              cat();
5689//         }"
5690//     ));
5691
5692//     // Multiple cursors on one line -> advance
5693//     cx.set_state(indoc!(
5694//         "fn a() {
5695//              ˇdˇog();
5696//              cat();
5697//         }"
5698//     ));
5699//     cx.update_editor(|editor, cx| {
5700//         editor.toggle_comments(toggle_comments, cx);
5701//     });
5702//     cx.assert_editor_state(indoc!(
5703//         "fn a() {
5704//              // dog();
5705//              catˇ(ˇ);
5706//         }"
5707//     ));
5708
5709//     // Multiple cursors on one line, with selection -> don't advance
5710//     cx.set_state(indoc!(
5711//         "fn a() {
5712//              ˇdˇog«()ˇ»;
5713//              cat();
5714//         }"
5715//     ));
5716//     cx.update_editor(|editor, cx| {
5717//         editor.toggle_comments(toggle_comments, cx);
5718//     });
5719//     cx.assert_editor_state(indoc!(
5720//         "fn a() {
5721//              // ˇdˇog«()ˇ»;
5722//              cat();
5723//         }"
5724//     ));
5725
5726//     // Single cursor on one line -> advance
5727//     // Cursor moves to column 0 on blank line
5728//     cx.set_state(indoc!(
5729//         "fn a() {
5730//              ˇdog();
5731
5732//              cat();
5733//         }"
5734//     ));
5735//     cx.update_editor(|editor, cx| {
5736//         editor.toggle_comments(toggle_comments, cx);
5737//     });
5738//     cx.assert_editor_state(indoc!(
5739//         "fn a() {
5740//              // dog();
5741//         ˇ
5742//              cat();
5743//         }"
5744//     ));
5745
5746//     // Single cursor on one line -> advance
5747//     // Cursor starts and ends at column 0
5748//     cx.set_state(indoc!(
5749//         "fn a() {
5750//          ˇ    dog();
5751//              cat();
5752//         }"
5753//     ));
5754//     cx.update_editor(|editor, cx| {
5755//         editor.toggle_comments(toggle_comments, cx);
5756//     });
5757//     cx.assert_editor_state(indoc!(
5758//         "fn a() {
5759//              // dog();
5760//          ˇ    cat();
5761//         }"
5762//     ));
5763// }
5764
5765// #[gpui::test]
5766// async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) {
5767//     init_test(cx, |_| {});
5768
5769//     let mut cx = EditorTestContext::new(cx).await;
5770
5771//     let html_language = Arc::new(
5772//         Language::new(
5773//             LanguageConfig {
5774//                 name: "HTML".into(),
5775//                 block_comment: Some(("<!-- ".into(), " -->".into())),
5776//                 ..Default::default()
5777//             },
5778//             Some(tree_sitter_html::language()),
5779//         )
5780//         .with_injection_query(
5781//             r#"
5782//             (script_element
5783//                 (raw_text) @content
5784//                 (#set! "language" "javascript"))
5785//             "#,
5786//         )
5787//         .unwrap(),
5788//     );
5789
5790//     let javascript_language = Arc::new(Language::new(
5791//         LanguageConfig {
5792//             name: "JavaScript".into(),
5793//             line_comment: Some("// ".into()),
5794//             ..Default::default()
5795//         },
5796//         Some(tree_sitter_typescript::language_tsx()),
5797//     ));
5798
5799//     let registry = Arc::new(LanguageRegistry::test());
5800//     registry.add(html_language.clone());
5801//     registry.add(javascript_language.clone());
5802
5803//     cx.update_buffer(|buffer, cx| {
5804//         buffer.set_language_registry(registry);
5805//         buffer.set_language(Some(html_language), cx);
5806//     });
5807
5808//     // Toggle comments for empty selections
5809//     cx.set_state(
5810//         &r#"
5811//             <p>A</p>ˇ
5812//             <p>B</p>ˇ
5813//             <p>C</p>ˇ
5814//         "#
5815//         .unindent(),
5816//     );
5817//     cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
5818//     cx.assert_editor_state(
5819//         &r#"
5820//             <!-- <p>A</p>ˇ -->
5821//             <!-- <p>B</p>ˇ -->
5822//             <!-- <p>C</p>ˇ -->
5823//         "#
5824//         .unindent(),
5825//     );
5826//     cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
5827//     cx.assert_editor_state(
5828//         &r#"
5829//             <p>A</p>ˇ
5830//             <p>B</p>ˇ
5831//             <p>C</p>ˇ
5832//         "#
5833//         .unindent(),
5834//     );
5835
5836//     // Toggle comments for mixture of empty and non-empty selections, where
5837//     // multiple selections occupy a given line.
5838//     cx.set_state(
5839//         &r#"
5840//             <p>A«</p>
5841//             <p>ˇ»B</p>ˇ
5842//             <p>C«</p>
5843//             <p>ˇ»D</p>ˇ
5844//         "#
5845//         .unindent(),
5846//     );
5847
5848//     cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
5849//     cx.assert_editor_state(
5850//         &r#"
5851//             <!-- <p>A«</p>
5852//             <p>ˇ»B</p>ˇ -->
5853//             <!-- <p>C«</p>
5854//             <p>ˇ»D</p>ˇ -->
5855//         "#
5856//         .unindent(),
5857//     );
5858//     cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
5859//     cx.assert_editor_state(
5860//         &r#"
5861//             <p>A«</p>
5862//             <p>ˇ»B</p>ˇ
5863//             <p>C«</p>
5864//             <p>ˇ»D</p>ˇ
5865//         "#
5866//         .unindent(),
5867//     );
5868
5869//     // Toggle comments when different languages are active for different
5870//     // selections.
5871//     cx.set_state(
5872//         &r#"
5873//             ˇ<script>
5874//                 ˇvar x = new Y();
5875//             ˇ</script>
5876//         "#
5877//         .unindent(),
5878//     );
5879//     cx.foreground().run_until_parked();
5880//     cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments::default(), cx));
5881//     cx.assert_editor_state(
5882//         &r#"
5883//             <!-- ˇ<script> -->
5884//                 // ˇvar x = new Y();
5885//             <!-- ˇ</script> -->
5886//         "#
5887//         .unindent(),
5888//     );
5889// }
5890
5891// #[gpui::test]
5892// fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
5893//     init_test(cx, |_| {});
5894
5895//     let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a')));
5896//     let multibuffer = cx.add_model(|cx| {
5897//         let mut multibuffer = MultiBuffer::new(0);
5898//         multibuffer.push_excerpts(
5899//             buffer.clone(),
5900//             [
5901//                 ExcerptRange {
5902//                     context: Point::new(0, 0)..Point::new(0, 4),
5903//                     primary: None,
5904//                 },
5905//                 ExcerptRange {
5906//                     context: Point::new(1, 0)..Point::new(1, 4),
5907//                     primary: None,
5908//                 },
5909//             ],
5910//             cx,
5911//         );
5912//         assert_eq!(multibuffer.read(cx).text(), "aaaa\nbbbb");
5913//         multibuffer
5914//     });
5915
5916//     let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
5917//     view.update(cx, |view, cx| {
5918//         assert_eq!(view.text(cx), "aaaa\nbbbb");
5919//         view.change_selections(None, cx, |s| {
5920//             s.select_ranges([
5921//                 Point::new(0, 0)..Point::new(0, 0),
5922//                 Point::new(1, 0)..Point::new(1, 0),
5923//             ])
5924//         });
5925
5926//         view.handle_input("X", cx);
5927//         assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
5928//         assert_eq!(
5929//             view.selections.ranges(cx),
5930//             [
5931//                 Point::new(0, 1)..Point::new(0, 1),
5932//                 Point::new(1, 1)..Point::new(1, 1),
5933//             ]
5934//         );
5935
5936//         // Ensure the cursor's head is respected when deleting across an excerpt boundary.
5937//         view.change_selections(None, cx, |s| {
5938//             s.select_ranges([Point::new(0, 2)..Point::new(1, 2)])
5939//         });
5940//         view.backspace(&Default::default(), cx);
5941//         assert_eq!(view.text(cx), "Xa\nbbb");
5942//         assert_eq!(
5943//             view.selections.ranges(cx),
5944//             [Point::new(1, 0)..Point::new(1, 0)]
5945//         );
5946
5947//         view.change_selections(None, cx, |s| {
5948//             s.select_ranges([Point::new(1, 1)..Point::new(0, 1)])
5949//         });
5950//         view.backspace(&Default::default(), cx);
5951//         assert_eq!(view.text(cx), "X\nbb");
5952//         assert_eq!(
5953//             view.selections.ranges(cx),
5954//             [Point::new(0, 1)..Point::new(0, 1)]
5955//         );
5956//     });
5957// }
5958
5959// #[gpui::test]
5960// fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
5961//     init_test(cx, |_| {});
5962
5963//     let markers = vec![('[', ']').into(), ('(', ')').into()];
5964//     let (initial_text, mut excerpt_ranges) = marked_text_ranges_by(
5965//         indoc! {"
5966//             [aaaa
5967//             (bbbb]
5968//             cccc)",
5969//         },
5970//         markers.clone(),
5971//     );
5972//     let excerpt_ranges = markers.into_iter().map(|marker| {
5973//         let context = excerpt_ranges.remove(&marker).unwrap()[0].clone();
5974//         ExcerptRange {
5975//             context,
5976//             primary: None,
5977//         }
5978//     });
5979//     let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, initial_text));
5980//     let multibuffer = cx.add_model(|cx| {
5981//         let mut multibuffer = MultiBuffer::new(0);
5982//         multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
5983//         multibuffer
5984//     });
5985
5986//     let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
5987//     view.update(cx, |view, cx| {
5988//         let (expected_text, selection_ranges) = marked_text_ranges(
5989//             indoc! {"
5990//                 aaaa
5991//                 bˇbbb
5992//                 bˇbbˇb
5993//                 cccc"
5994//             },
5995//             true,
5996//         );
5997//         assert_eq!(view.text(cx), expected_text);
5998//         view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
5999
6000//         view.handle_input("X", cx);
6001
6002//         let (expected_text, expected_selections) = marked_text_ranges(
6003//             indoc! {"
6004//                 aaaa
6005//                 bXˇbbXb
6006//                 bXˇbbXˇb
6007//                 cccc"
6008//             },
6009//             false,
6010//         );
6011//         assert_eq!(view.text(cx), expected_text);
6012//         assert_eq!(view.selections.ranges(cx), expected_selections);
6013
6014//         view.newline(&Newline, cx);
6015//         let (expected_text, expected_selections) = marked_text_ranges(
6016//             indoc! {"
6017//                 aaaa
6018//                 bX
6019//                 ˇbbX
6020//                 b
6021//                 bX
6022//                 ˇbbX
6023//                 ˇb
6024//                 cccc"
6025//             },
6026//             false,
6027//         );
6028//         assert_eq!(view.text(cx), expected_text);
6029//         assert_eq!(view.selections.ranges(cx), expected_selections);
6030//     });
6031// }
6032
6033// #[gpui::test]
6034// fn test_refresh_selections(cx: &mut TestAppContext) {
6035//     init_test(cx, |_| {});
6036
6037//     let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a')));
6038//     let mut excerpt1_id = None;
6039//     let multibuffer = cx.add_model(|cx| {
6040//         let mut multibuffer = MultiBuffer::new(0);
6041//         excerpt1_id = multibuffer
6042//             .push_excerpts(
6043//                 buffer.clone(),
6044//                 [
6045//                     ExcerptRange {
6046//                         context: Point::new(0, 0)..Point::new(1, 4),
6047//                         primary: None,
6048//                     },
6049//                     ExcerptRange {
6050//                         context: Point::new(1, 0)..Point::new(2, 4),
6051//                         primary: None,
6052//                     },
6053//                 ],
6054//                 cx,
6055//             )
6056//             .into_iter()
6057//             .next();
6058//         assert_eq!(multibuffer.read(cx).text(), "aaaa\nbbbb\nbbbb\ncccc");
6059//         multibuffer
6060//     });
6061
6062//     let editor = cx
6063//         .add_window(|cx| {
6064//             let mut editor = build_editor(multibuffer.clone(), cx);
6065//             let snapshot = editor.snapshot(cx);
6066//             editor.change_selections(None, cx, |s| {
6067//                 s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
6068//             });
6069//             editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
6070//             assert_eq!(
6071//                 editor.selections.ranges(cx),
6072//                 [
6073//                     Point::new(1, 3)..Point::new(1, 3),
6074//                     Point::new(2, 1)..Point::new(2, 1),
6075//                 ]
6076//             );
6077//             editor
6078//         })
6079//         .root(cx);
6080
6081//     // Refreshing selections is a no-op when excerpts haven't changed.
6082//     editor.update(cx, |editor, cx| {
6083//         editor.change_selections(None, cx, |s| s.refresh());
6084//         assert_eq!(
6085//             editor.selections.ranges(cx),
6086//             [
6087//                 Point::new(1, 3)..Point::new(1, 3),
6088//                 Point::new(2, 1)..Point::new(2, 1),
6089//             ]
6090//         );
6091//     });
6092
6093//     multibuffer.update(cx, |multibuffer, cx| {
6094//         multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx);
6095//     });
6096//     editor.update(cx, |editor, cx| {
6097//         // Removing an excerpt causes the first selection to become degenerate.
6098//         assert_eq!(
6099//             editor.selections.ranges(cx),
6100//             [
6101//                 Point::new(0, 0)..Point::new(0, 0),
6102//                 Point::new(0, 1)..Point::new(0, 1)
6103//             ]
6104//         );
6105
6106//         // Refreshing selections will relocate the first selection to the original buffer
6107//         // location.
6108//         editor.change_selections(None, cx, |s| s.refresh());
6109//         assert_eq!(
6110//             editor.selections.ranges(cx),
6111//             [
6112//                 Point::new(0, 1)..Point::new(0, 1),
6113//                 Point::new(0, 3)..Point::new(0, 3)
6114//             ]
6115//         );
6116//         assert!(editor.selections.pending_anchor().is_some());
6117//     });
6118// }
6119
6120// #[gpui::test]
6121// fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
6122//     init_test(cx, |_| {});
6123
6124//     let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a')));
6125//     let mut excerpt1_id = None;
6126//     let multibuffer = cx.add_model(|cx| {
6127//         let mut multibuffer = MultiBuffer::new(0);
6128//         excerpt1_id = multibuffer
6129//             .push_excerpts(
6130//                 buffer.clone(),
6131//                 [
6132//                     ExcerptRange {
6133//                         context: Point::new(0, 0)..Point::new(1, 4),
6134//                         primary: None,
6135//                     },
6136//                     ExcerptRange {
6137//                         context: Point::new(1, 0)..Point::new(2, 4),
6138//                         primary: None,
6139//                     },
6140//                 ],
6141//                 cx,
6142//             )
6143//             .into_iter()
6144//             .next();
6145//         assert_eq!(multibuffer.read(cx).text(), "aaaa\nbbbb\nbbbb\ncccc");
6146//         multibuffer
6147//     });
6148
6149//     let editor = cx
6150//         .add_window(|cx| {
6151//             let mut editor = build_editor(multibuffer.clone(), cx);
6152//             let snapshot = editor.snapshot(cx);
6153//             editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
6154//             assert_eq!(
6155//                 editor.selections.ranges(cx),
6156//                 [Point::new(1, 3)..Point::new(1, 3)]
6157//             );
6158//             editor
6159//         })
6160//         .root(cx);
6161
6162//     multibuffer.update(cx, |multibuffer, cx| {
6163//         multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx);
6164//     });
6165//     editor.update(cx, |editor, cx| {
6166//         assert_eq!(
6167//             editor.selections.ranges(cx),
6168//             [Point::new(0, 0)..Point::new(0, 0)]
6169//         );
6170
6171//         // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
6172//         editor.change_selections(None, cx, |s| s.refresh());
6173//         assert_eq!(
6174//             editor.selections.ranges(cx),
6175//             [Point::new(0, 3)..Point::new(0, 3)]
6176//         );
6177//         assert!(editor.selections.pending_anchor().is_some());
6178//     });
6179// }
6180
6181// #[gpui::test]
6182// async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
6183//     init_test(cx, |_| {});
6184
6185//     let language = Arc::new(
6186//         Language::new(
6187//             LanguageConfig {
6188//                 brackets: BracketPairConfig {
6189//                     pairs: vec![
6190//                         BracketPair {
6191//                             start: "{".to_string(),
6192//                             end: "}".to_string(),
6193//                             close: true,
6194//                             newline: true,
6195//                         },
6196//                         BracketPair {
6197//                             start: "/* ".to_string(),
6198//                             end: " */".to_string(),
6199//                             close: true,
6200//                             newline: true,
6201//                         },
6202//                     ],
6203//                     ..Default::default()
6204//                 },
6205//                 ..Default::default()
6206//             },
6207//             Some(tree_sitter_rust::language()),
6208//         )
6209//         .with_indents_query("")
6210//         .unwrap(),
6211//     );
6212
6213//     let text = concat!(
6214//         "{   }\n",     //
6215//         "  x\n",       //
6216//         "  /*   */\n", //
6217//         "x\n",         //
6218//         "{{} }\n",     //
6219//     );
6220
6221//     let buffer =
6222//         cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx));
6223//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
6224//     let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
6225//     view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
6226//         .await;
6227
6228//     view.update(cx, |view, cx| {
6229//         view.change_selections(None, cx, |s| {
6230//             s.select_display_ranges([
6231//                 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
6232//                 DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
6233//                 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
6234//             ])
6235//         });
6236//         view.newline(&Newline, cx);
6237
6238//         assert_eq!(
6239//             view.buffer().read(cx).read(cx).text(),
6240//             concat!(
6241//                 "{ \n",    // Suppress rustfmt
6242//                 "\n",      //
6243//                 "}\n",     //
6244//                 "  x\n",   //
6245//                 "  /* \n", //
6246//                 "  \n",    //
6247//                 "  */\n",  //
6248//                 "x\n",     //
6249//                 "{{} \n",  //
6250//                 "}\n",     //
6251//             )
6252//         );
6253//     });
6254// }
6255
6256// #[gpui::test]
6257// fn test_highlighted_ranges(cx: &mut TestAppContext) {
6258//     init_test(cx, |_| {});
6259
6260//     let editor = cx
6261//         .add_window(|cx| {
6262//             let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
6263//             build_editor(buffer.clone(), cx)
6264//         })
6265//         .root(cx);
6266
6267//     editor.update(cx, |editor, cx| {
6268//         struct Type1;
6269//         struct Type2;
6270
6271//         let buffer = editor.buffer.read(cx).snapshot(cx);
6272
6273//         let anchor_range =
6274//             |range: Range<Point>| buffer.anchor_after(range.start)..buffer.anchor_after(range.end);
6275
6276//         editor.highlight_background::<Type1>(
6277//             vec![
6278//                 anchor_range(Point::new(2, 1)..Point::new(2, 3)),
6279//                 anchor_range(Point::new(4, 2)..Point::new(4, 4)),
6280//                 anchor_range(Point::new(6, 3)..Point::new(6, 5)),
6281//                 anchor_range(Point::new(8, 4)..Point::new(8, 6)),
6282//             ],
6283//             |_| Hsla::red(),
6284//             cx,
6285//         );
6286//         editor.highlight_background::<Type2>(
6287//             vec![
6288//                 anchor_range(Point::new(3, 2)..Point::new(3, 5)),
6289//                 anchor_range(Point::new(5, 3)..Point::new(5, 6)),
6290//                 anchor_range(Point::new(7, 4)..Point::new(7, 7)),
6291//                 anchor_range(Point::new(9, 5)..Point::new(9, 8)),
6292//             ],
6293//             |_| Hsla::green(),
6294//             cx,
6295//         );
6296
6297//         let snapshot = editor.snapshot(cx);
6298//         let mut highlighted_ranges = editor.background_highlights_in_range(
6299//             anchor_range(Point::new(3, 4)..Point::new(7, 4)),
6300//             &snapshot,
6301//             theme::current(cx).as_ref(),
6302//         );
6303//         // Enforce a consistent ordering based on color without relying on the ordering of the
6304//         // highlight's `TypeId` which is non-deterministic.
6305//         highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
6306//         assert_eq!(
6307//             highlighted_ranges,
6308//             &[
6309//                 (
6310//                     DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
6311//                     Hsla::green(),
6312//                 ),
6313//                 (
6314//                     DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
6315//                     Hsla::green(),
6316//                 ),
6317//                 (
6318//                     DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
6319//                     Hsla::red(),
6320//                 ),
6321//                 (
6322//                     DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
6323//                     Hsla::red(),
6324//                 ),
6325//             ]
6326//         );
6327//         assert_eq!(
6328//             editor.background_highlights_in_range(
6329//                 anchor_range(Point::new(5, 6)..Point::new(6, 4)),
6330//                 &snapshot,
6331//                 theme::current(cx).as_ref(),
6332//             ),
6333//             &[(
6334//                 DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
6335//                 Hsla::red(),
6336//             )]
6337//         );
6338//     });
6339// }
6340
6341// #[gpui::test]
6342// async fn test_following(cx: &mut gpui::TestAppContext) {
6343//     init_test(cx, |_| {});
6344
6345//     let fs = FakeFs::new(cx.background());
6346//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
6347
6348//     let buffer = project.update(cx, |project, cx| {
6349//         let buffer = project
6350//             .create_buffer(&sample_text(16, 8, 'a'), None, cx)
6351//             .unwrap();
6352//         cx.add_model(|cx| MultiBuffer::singleton(buffer, cx))
6353//     });
6354//     let leader = cx
6355//         .add_window(|cx| build_editor(buffer.clone(), cx))
6356//         .root(cx);
6357//     let follower = cx
6358//         .update(|cx| {
6359//             cx.add_window(
6360//                 WindowOptions {
6361//                     bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
6362//                     ..Default::default()
6363//                 },
6364//                 |cx| build_editor(buffer.clone(), cx),
6365//             )
6366//         })
6367//         .root(cx);
6368
6369//     let is_still_following = Rc::new(RefCell::new(true));
6370//     let follower_edit_event_count = Rc::new(RefCell::new(0));
6371//     let pending_update = Rc::new(RefCell::new(None));
6372//     follower.update(cx, {
6373//         let update = pending_update.clone();
6374//         let is_still_following = is_still_following.clone();
6375//         let follower_edit_event_count = follower_edit_event_count.clone();
6376//         |_, cx| {
6377//             cx.subscribe(&leader, move |_, leader, event, cx| {
6378//                 leader
6379//                     .read(cx)
6380//                     .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
6381//             })
6382//             .detach();
6383
6384//             cx.subscribe(&follower, move |_, _, event, cx| {
6385//                 if Editor::should_unfollow_on_event(event, cx) {
6386//                     *is_still_following.borrow_mut() = false;
6387//                 }
6388//                 if let Event::BufferEdited = event {
6389//                     *follower_edit_event_count.borrow_mut() += 1;
6390//                 }
6391//             })
6392//             .detach();
6393//         }
6394//     });
6395
6396//     // Update the selections only
6397//     leader.update(cx, |leader, cx| {
6398//         leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
6399//     });
6400//     follower
6401//         .update(cx, |follower, cx| {
6402//             follower.apply_update_proto(&project, pending_update.borrow_mut().take().unwrap(), cx)
6403//         })
6404//         .await
6405//         .unwrap();
6406//     follower.read_with(cx, |follower, cx| {
6407//         assert_eq!(follower.selections.ranges(cx), vec![1..1]);
6408//     });
6409//     assert_eq!(*is_still_following.borrow(), true);
6410//     assert_eq!(*follower_edit_event_count.borrow(), 0);
6411
6412//     // Update the scroll position only
6413//     leader.update(cx, |leader, cx| {
6414//         leader.set_scroll_position(vec2f(1.5, 3.5), cx);
6415//     });
6416//     follower
6417//         .update(cx, |follower, cx| {
6418//             follower.apply_update_proto(&project, pending_update.borrow_mut().take().unwrap(), cx)
6419//         })
6420//         .await
6421//         .unwrap();
6422//     assert_eq!(
6423//         follower.update(cx, |follower, cx| follower.scroll_position(cx)),
6424//         vec2f(1.5, 3.5)
6425//     );
6426//     assert_eq!(*is_still_following.borrow(), true);
6427//     assert_eq!(*follower_edit_event_count.borrow(), 0);
6428
6429//     // Update the selections and scroll position. The follower's scroll position is updated
6430//     // via autoscroll, not via the leader's exact scroll position.
6431//     leader.update(cx, |leader, cx| {
6432//         leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
6433//         leader.request_autoscroll(Autoscroll::newest(), cx);
6434//         leader.set_scroll_position(vec2f(1.5, 3.5), cx);
6435//     });
6436//     follower
6437//         .update(cx, |follower, cx| {
6438//             follower.apply_update_proto(&project, pending_update.borrow_mut().take().unwrap(), cx)
6439//         })
6440//         .await
6441//         .unwrap();
6442//     follower.update(cx, |follower, cx| {
6443//         assert_eq!(follower.scroll_position(cx), vec2f(1.5, 0.0));
6444//         assert_eq!(follower.selections.ranges(cx), vec![0..0]);
6445//     });
6446//     assert_eq!(*is_still_following.borrow(), true);
6447
6448//     // Creating a pending selection that precedes another selection
6449//     leader.update(cx, |leader, cx| {
6450//         leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
6451//         leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
6452//     });
6453//     follower
6454//         .update(cx, |follower, cx| {
6455//             follower.apply_update_proto(&project, pending_update.borrow_mut().take().unwrap(), cx)
6456//         })
6457//         .await
6458//         .unwrap();
6459//     follower.read_with(cx, |follower, cx| {
6460//         assert_eq!(follower.selections.ranges(cx), vec![0..0, 1..1]);
6461//     });
6462//     assert_eq!(*is_still_following.borrow(), true);
6463
6464//     // Extend the pending selection so that it surrounds another selection
6465//     leader.update(cx, |leader, cx| {
6466//         leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
6467//     });
6468//     follower
6469//         .update(cx, |follower, cx| {
6470//             follower.apply_update_proto(&project, pending_update.borrow_mut().take().unwrap(), cx)
6471//         })
6472//         .await
6473//         .unwrap();
6474//     follower.read_with(cx, |follower, cx| {
6475//         assert_eq!(follower.selections.ranges(cx), vec![0..2]);
6476//     });
6477
6478//     // Scrolling locally breaks the follow
6479//     follower.update(cx, |follower, cx| {
6480//         let top_anchor = follower.buffer().read(cx).read(cx).anchor_after(0);
6481//         follower.set_scroll_anchor(
6482//             ScrollAnchor {
6483//                 anchor: top_anchor,
6484//                 offset: vec2f(0.0, 0.5),
6485//             },
6486//             cx,
6487//         );
6488//     });
6489//     assert_eq!(*is_still_following.borrow(), false);
6490// }
6491
6492// #[gpui::test]
6493// async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
6494//     init_test(cx, |_| {});
6495
6496//     let fs = FakeFs::new(cx.background());
6497//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
6498//     let workspace = cx
6499//         .add_window(|cx| Workspace::test_new(project.clone(), cx))
6500//         .root(cx);
6501//     let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
6502
6503//     let leader = pane.update(cx, |_, cx| {
6504//         let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
6505//         cx.add_view(|cx| build_editor(multibuffer.clone(), cx))
6506//     });
6507
6508//     // Start following the editor when it has no excerpts.
6509//     let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
6510//     let follower_1 = cx
6511//         .update(|cx| {
6512//             Editor::from_state_proto(
6513//                 pane.clone(),
6514//                 workspace.clone(),
6515//                 ViewId {
6516//                     creator: Default::default(),
6517//                     id: 0,
6518//                 },
6519//                 &mut state_message,
6520//                 cx,
6521//             )
6522//         })
6523//         .unwrap()
6524//         .await
6525//         .unwrap();
6526
6527//     let update_message = Rc::new(RefCell::new(None));
6528//     follower_1.update(cx, {
6529//         let update = update_message.clone();
6530//         |_, cx| {
6531//             cx.subscribe(&leader, move |_, leader, event, cx| {
6532//                 leader
6533//                     .read(cx)
6534//                     .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
6535//             })
6536//             .detach();
6537//         }
6538//     });
6539
6540//     let (buffer_1, buffer_2) = project.update(cx, |project, cx| {
6541//         (
6542//             project
6543//                 .create_buffer("abc\ndef\nghi\njkl\n", None, cx)
6544//                 .unwrap(),
6545//             project
6546//                 .create_buffer("mno\npqr\nstu\nvwx\n", None, cx)
6547//                 .unwrap(),
6548//         )
6549//     });
6550
6551//     // Insert some excerpts.
6552//     leader.update(cx, |leader, cx| {
6553//         leader.buffer.update(cx, |multibuffer, cx| {
6554//             let excerpt_ids = multibuffer.push_excerpts(
6555//                 buffer_1.clone(),
6556//                 [
6557//                     ExcerptRange {
6558//                         context: 1..6,
6559//                         primary: None,
6560//                     },
6561//                     ExcerptRange {
6562//                         context: 12..15,
6563//                         primary: None,
6564//                     },
6565//                     ExcerptRange {
6566//                         context: 0..3,
6567//                         primary: None,
6568//                     },
6569//                 ],
6570//                 cx,
6571//             );
6572//             multibuffer.insert_excerpts_after(
6573//                 excerpt_ids[0],
6574//                 buffer_2.clone(),
6575//                 [
6576//                     ExcerptRange {
6577//                         context: 8..12,
6578//                         primary: None,
6579//                     },
6580//                     ExcerptRange {
6581//                         context: 0..6,
6582//                         primary: None,
6583//                     },
6584//                 ],
6585//                 cx,
6586//             );
6587//         });
6588//     });
6589
6590//     // Apply the update of adding the excerpts.
6591//     follower_1
6592//         .update(cx, |follower, cx| {
6593//             follower.apply_update_proto(&project, update_message.borrow().clone().unwrap(), cx)
6594//         })
6595//         .await
6596//         .unwrap();
6597//     assert_eq!(
6598//         follower_1.read_with(cx, |editor, cx| editor.text(cx)),
6599//         leader.read_with(cx, |editor, cx| editor.text(cx))
6600//     );
6601//     update_message.borrow_mut().take();
6602
6603//     // Start following separately after it already has excerpts.
6604//     let mut state_message = leader.update(cx, |leader, cx| leader.to_state_proto(cx));
6605//     let follower_2 = cx
6606//         .update(|cx| {
6607//             Editor::from_state_proto(
6608//                 pane.clone(),
6609//                 workspace.clone(),
6610//                 ViewId {
6611//                     creator: Default::default(),
6612//                     id: 0,
6613//                 },
6614//                 &mut state_message,
6615//                 cx,
6616//             )
6617//         })
6618//         .unwrap()
6619//         .await
6620//         .unwrap();
6621//     assert_eq!(
6622//         follower_2.read_with(cx, |editor, cx| editor.text(cx)),
6623//         leader.read_with(cx, |editor, cx| editor.text(cx))
6624//     );
6625
6626//     // Remove some excerpts.
6627//     leader.update(cx, |leader, cx| {
6628//         leader.buffer.update(cx, |multibuffer, cx| {
6629//             let excerpt_ids = multibuffer.excerpt_ids();
6630//             multibuffer.remove_excerpts([excerpt_ids[1], excerpt_ids[2]], cx);
6631//             multibuffer.remove_excerpts([excerpt_ids[0]], cx);
6632//         });
6633//     });
6634
6635//     // Apply the update of removing the excerpts.
6636//     follower_1
6637//         .update(cx, |follower, cx| {
6638//             follower.apply_update_proto(&project, update_message.borrow().clone().unwrap(), cx)
6639//         })
6640//         .await
6641//         .unwrap();
6642//     follower_2
6643//         .update(cx, |follower, cx| {
6644//             follower.apply_update_proto(&project, update_message.borrow().clone().unwrap(), cx)
6645//         })
6646//         .await
6647//         .unwrap();
6648//     update_message.borrow_mut().take();
6649//     assert_eq!(
6650//         follower_1.read_with(cx, |editor, cx| editor.text(cx)),
6651//         leader.read_with(cx, |editor, cx| editor.text(cx))
6652//     );
6653// }
6654
6655// #[test]
6656// fn test_combine_syntax_and_fuzzy_match_highlights() {
6657//     let string = "abcdefghijklmnop";
6658//     let syntax_ranges = [
6659//         (
6660//             0..3,
6661//             HighlightStyle {
6662//                 color: Some(Hsla::red()),
6663//                 ..Default::default()
6664//             },
6665//         ),
6666//         (
6667//             4..8,
6668//             HighlightStyle {
6669//                 color: Some(Hsla::green()),
6670//                 ..Default::default()
6671//             },
6672//         ),
6673//     ];
6674//     let match_indices = [4, 6, 7, 8];
6675//     assert_eq!(
6676//         combine_syntax_and_fuzzy_match_highlights(
6677//             string,
6678//             Default::default(),
6679//             syntax_ranges.into_iter(),
6680//             &match_indices,
6681//         ),
6682//         &[
6683//             (
6684//                 0..3,
6685//                 HighlightStyle {
6686//                     color: Some(Hsla::red()),
6687//                     ..Default::default()
6688//                 },
6689//             ),
6690//             (
6691//                 4..5,
6692//                 HighlightStyle {
6693//                     color: Some(Hsla::green()),
6694//                     weight: Some(fonts::Weight::BOLD),
6695//                     ..Default::default()
6696//                 },
6697//             ),
6698//             (
6699//                 5..6,
6700//                 HighlightStyle {
6701//                     color: Some(Hsla::green()),
6702//                     ..Default::default()
6703//                 },
6704//             ),
6705//             (
6706//                 6..8,
6707//                 HighlightStyle {
6708//                     color: Some(Hsla::green()),
6709//                     weight: Some(fonts::Weight::BOLD),
6710//                     ..Default::default()
6711//                 },
6712//             ),
6713//             (
6714//                 8..9,
6715//                 HighlightStyle {
6716//                     weight: Some(fonts::Weight::BOLD),
6717//                     ..Default::default()
6718//                 },
6719//             ),
6720//         ]
6721//     );
6722// }
6723
6724// #[gpui::test]
6725// async fn go_to_prev_overlapping_diagnostic(
6726//     deterministic: Arc<Deterministic>,
6727//     cx: &mut gpui::TestAppContext,
6728// ) {
6729//     init_test(cx, |_| {});
6730
6731//     let mut cx = EditorTestContext::new(cx).await;
6732//     let project = cx.update_editor(|editor, _| editor.project.clone().unwrap());
6733
6734//     cx.set_state(indoc! {"
6735//         ˇfn func(abc def: i32) -> u32 {
6736//         }
6737//     "});
6738
6739//     cx.update(|cx| {
6740//         project.update(cx, |project, cx| {
6741//             project
6742//                 .update_diagnostics(
6743//                     LanguageServerId(0),
6744//                     lsp::PublishDiagnosticsParams {
6745//                         uri: lsp::Url::from_file_path("/root/file").unwrap(),
6746//                         version: None,
6747//                         diagnostics: vec![
6748//                             lsp::Diagnostic {
6749//                                 range: lsp::Range::new(
6750//                                     lsp::Position::new(0, 11),
6751//                                     lsp::Position::new(0, 12),
6752//                                 ),
6753//                                 severity: Some(lsp::DiagnosticSeverity::ERROR),
6754//                                 ..Default::default()
6755//                             },
6756//                             lsp::Diagnostic {
6757//                                 range: lsp::Range::new(
6758//                                     lsp::Position::new(0, 12),
6759//                                     lsp::Position::new(0, 15),
6760//                                 ),
6761//                                 severity: Some(lsp::DiagnosticSeverity::ERROR),
6762//                                 ..Default::default()
6763//                             },
6764//                             lsp::Diagnostic {
6765//                                 range: lsp::Range::new(
6766//                                     lsp::Position::new(0, 25),
6767//                                     lsp::Position::new(0, 28),
6768//                                 ),
6769//                                 severity: Some(lsp::DiagnosticSeverity::ERROR),
6770//                                 ..Default::default()
6771//                             },
6772//                         ],
6773//                     },
6774//                     &[],
6775//                     cx,
6776//                 )
6777//                 .unwrap()
6778//         });
6779//     });
6780
6781//     deterministic.run_until_parked();
6782
6783//     cx.update_editor(|editor, cx| {
6784//         editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, cx);
6785//     });
6786
6787//     cx.assert_editor_state(indoc! {"
6788//         fn func(abc def: i32) -> ˇu32 {
6789//         }
6790//     "});
6791
6792//     cx.update_editor(|editor, cx| {
6793//         editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, cx);
6794//     });
6795
6796//     cx.assert_editor_state(indoc! {"
6797//         fn func(abc ˇdef: i32) -> u32 {
6798//         }
6799//     "});
6800
6801//     cx.update_editor(|editor, cx| {
6802//         editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, cx);
6803//     });
6804
6805//     cx.assert_editor_state(indoc! {"
6806//         fn func(abcˇ def: i32) -> u32 {
6807//         }
6808//     "});
6809
6810//     cx.update_editor(|editor, cx| {
6811//         editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, cx);
6812//     });
6813
6814//     cx.assert_editor_state(indoc! {"
6815//         fn func(abc def: i32) -> ˇu32 {
6816//         }
6817//     "});
6818// }
6819
6820// #[gpui::test]
6821// async fn go_to_hunk(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
6822//     init_test(cx, |_| {});
6823
6824//     let mut cx = EditorTestContext::new(cx).await;
6825
6826//     let diff_base = r#"
6827//         use some::mod;
6828
6829//         const A: u32 = 42;
6830
6831//         fn main() {
6832//             println!("hello");
6833
6834//             println!("world");
6835//         }
6836//         "#
6837//     .unindent();
6838
6839//     // Edits are modified, removed, modified, added
6840//     cx.set_state(
6841//         &r#"
6842//         use some::modified;
6843
6844//         ˇ
6845//         fn main() {
6846//             println!("hello there");
6847
6848//             println!("around the");
6849//             println!("world");
6850//         }
6851//         "#
6852//         .unindent(),
6853//     );
6854
6855//     cx.set_diff_base(Some(&diff_base));
6856//     deterministic.run_until_parked();
6857
6858//     cx.update_editor(|editor, cx| {
6859//         //Wrap around the bottom of the buffer
6860//         for _ in 0..3 {
6861//             editor.go_to_hunk(&GoToHunk, cx);
6862//         }
6863//     });
6864
6865//     cx.assert_editor_state(
6866//         &r#"
6867//         ˇuse some::modified;
6868
6869//         fn main() {
6870//             println!("hello there");
6871
6872//             println!("around the");
6873//             println!("world");
6874//         }
6875//         "#
6876//         .unindent(),
6877//     );
6878
6879//     cx.update_editor(|editor, cx| {
6880//         //Wrap around the top of the buffer
6881//         for _ in 0..2 {
6882//             editor.go_to_prev_hunk(&GoToPrevHunk, cx);
6883//         }
6884//     });
6885
6886//     cx.assert_editor_state(
6887//         &r#"
6888//         use some::modified;
6889
6890//         fn main() {
6891//         ˇ    println!("hello there");
6892
6893//             println!("around the");
6894//             println!("world");
6895//         }
6896//         "#
6897//         .unindent(),
6898//     );
6899
6900//     cx.update_editor(|editor, cx| {
6901//         editor.go_to_prev_hunk(&GoToPrevHunk, cx);
6902//     });
6903
6904//     cx.assert_editor_state(
6905//         &r#"
6906//         use some::modified;
6907
6908//         ˇ
6909//         fn main() {
6910//             println!("hello there");
6911
6912//             println!("around the");
6913//             println!("world");
6914//         }
6915//         "#
6916//         .unindent(),
6917//     );
6918
6919//     cx.update_editor(|editor, cx| {
6920//         for _ in 0..3 {
6921//             editor.go_to_prev_hunk(&GoToPrevHunk, cx);
6922//         }
6923//     });
6924
6925//     cx.assert_editor_state(
6926//         &r#"
6927//         use some::modified;
6928
6929//         fn main() {
6930//         ˇ    println!("hello there");
6931
6932//             println!("around the");
6933//             println!("world");
6934//         }
6935//         "#
6936//         .unindent(),
6937//     );
6938
6939//     cx.update_editor(|editor, cx| {
6940//         editor.fold(&Fold, cx);
6941
6942//         //Make sure that the fold only gets one hunk
6943//         for _ in 0..4 {
6944//             editor.go_to_hunk(&GoToHunk, cx);
6945//         }
6946//     });
6947
6948//     cx.assert_editor_state(
6949//         &r#"
6950//         ˇuse some::modified;
6951
6952//         fn main() {
6953//             println!("hello there");
6954
6955//             println!("around the");
6956//             println!("world");
6957//         }
6958//         "#
6959//         .unindent(),
6960//     );
6961// }
6962
6963// #[test]
6964// fn test_split_words() {
6965//     fn split<'a>(text: &'a str) -> Vec<&'a str> {
6966//         split_words(text).collect()
6967//     }
6968
6969//     assert_eq!(split("HelloWorld"), &["Hello", "World"]);
6970//     assert_eq!(split("hello_world"), &["hello_", "world"]);
6971//     assert_eq!(split("_hello_world_"), &["_", "hello_", "world_"]);
6972//     assert_eq!(split("Hello_World"), &["Hello_", "World"]);
6973//     assert_eq!(split("helloWOrld"), &["hello", "WOrld"]);
6974//     assert_eq!(split("helloworld"), &["helloworld"]);
6975// }
6976
6977// #[gpui::test]
6978// async fn test_move_to_enclosing_bracket(cx: &mut gpui::TestAppContext) {
6979//     init_test(cx, |_| {});
6980
6981//     let mut cx = EditorLspTestContext::new_typescript(Default::default(), cx).await;
6982//     let mut assert = |before, after| {
6983//         let _state_context = cx.set_state(before);
6984//         cx.update_editor(|editor, cx| {
6985//             editor.move_to_enclosing_bracket(&MoveToEnclosingBracket, cx)
6986//         });
6987//         cx.assert_editor_state(after);
6988//     };
6989
6990//     // Outside bracket jumps to outside of matching bracket
6991//     assert("console.logˇ(var);", "console.log(var)ˇ;");
6992//     assert("console.log(var)ˇ;", "console.logˇ(var);");
6993
6994//     // Inside bracket jumps to inside of matching bracket
6995//     assert("console.log(ˇvar);", "console.log(varˇ);");
6996//     assert("console.log(varˇ);", "console.log(ˇvar);");
6997
6998//     // When outside a bracket and inside, favor jumping to the inside bracket
6999//     assert(
7000//         "console.log('foo', [1, 2, 3]ˇ);",
7001//         "console.log(ˇ'foo', [1, 2, 3]);",
7002//     );
7003//     assert(
7004//         "console.log(ˇ'foo', [1, 2, 3]);",
7005//         "console.log('foo', [1, 2, 3]ˇ);",
7006//     );
7007
7008//     // Bias forward if two options are equally likely
7009//     assert(
7010//         "let result = curried_fun()ˇ();",
7011//         "let result = curried_fun()()ˇ;",
7012//     );
7013
7014//     // If directly adjacent to a smaller pair but inside a larger (not adjacent), pick the smaller
7015//     assert(
7016//         indoc! {"
7017//             function test() {
7018//                 console.log('test')ˇ
7019//             }"},
7020//         indoc! {"
7021//             function test() {
7022//                 console.logˇ('test')
7023//             }"},
7024//     );
7025// }
7026
7027// #[gpui::test(iterations = 10)]
7028// async fn test_copilot(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
7029//     init_test(cx, |_| {});
7030
7031//     let (copilot, copilot_lsp) = Copilot::fake(cx);
7032//     cx.update(|cx| cx.set_global(copilot));
7033//     let mut cx = EditorLspTestContext::new_rust(
7034//         lsp::ServerCapabilities {
7035//             completion_provider: Some(lsp::CompletionOptions {
7036//                 trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
7037//                 ..Default::default()
7038//             }),
7039//             ..Default::default()
7040//         },
7041//         cx,
7042//     )
7043//     .await;
7044
7045//     // When inserting, ensure autocompletion is favored over Copilot suggestions.
7046//     cx.set_state(indoc! {"
7047//         oneˇ
7048//         two
7049//         three
7050//     "});
7051//     cx.simulate_keystroke(".");
7052//     let _ = handle_completion_request(
7053//         &mut cx,
7054//         indoc! {"
7055//             one.|<>
7056//             two
7057//             three
7058//         "},
7059//         vec!["completion_a", "completion_b"],
7060//     );
7061//     handle_copilot_completion_request(
7062//         &copilot_lsp,
7063//         vec![copilot::request::Completion {
7064//             text: "one.copilot1".into(),
7065//             range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 4)),
7066//             ..Default::default()
7067//         }],
7068//         vec![],
7069//     );
7070//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7071//     cx.update_editor(|editor, cx| {
7072//         assert!(editor.context_menu_visible());
7073//         assert!(!editor.has_active_copilot_suggestion(cx));
7074
7075//         // Confirming a completion inserts it and hides the context menu, without showing
7076//         // the copilot suggestion afterwards.
7077//         editor
7078//             .confirm_completion(&Default::default(), cx)
7079//             .unwrap()
7080//             .detach();
7081//         assert!(!editor.context_menu_visible());
7082//         assert!(!editor.has_active_copilot_suggestion(cx));
7083//         assert_eq!(editor.text(cx), "one.completion_a\ntwo\nthree\n");
7084//         assert_eq!(editor.display_text(cx), "one.completion_a\ntwo\nthree\n");
7085//     });
7086
7087//     // Ensure Copilot suggestions are shown right away if no autocompletion is available.
7088//     cx.set_state(indoc! {"
7089//         oneˇ
7090//         two
7091//         three
7092//     "});
7093//     cx.simulate_keystroke(".");
7094//     let _ = handle_completion_request(
7095//         &mut cx,
7096//         indoc! {"
7097//             one.|<>
7098//             two
7099//             three
7100//         "},
7101//         vec![],
7102//     );
7103//     handle_copilot_completion_request(
7104//         &copilot_lsp,
7105//         vec![copilot::request::Completion {
7106//             text: "one.copilot1".into(),
7107//             range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 4)),
7108//             ..Default::default()
7109//         }],
7110//         vec![],
7111//     );
7112//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7113//     cx.update_editor(|editor, cx| {
7114//         assert!(!editor.context_menu_visible());
7115//         assert!(editor.has_active_copilot_suggestion(cx));
7116//         assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
7117//         assert_eq!(editor.text(cx), "one.\ntwo\nthree\n");
7118//     });
7119
7120//     // Reset editor, and ensure autocompletion is still favored over Copilot suggestions.
7121//     cx.set_state(indoc! {"
7122//         oneˇ
7123//         two
7124//         three
7125//     "});
7126//     cx.simulate_keystroke(".");
7127//     let _ = handle_completion_request(
7128//         &mut cx,
7129//         indoc! {"
7130//             one.|<>
7131//             two
7132//             three
7133//         "},
7134//         vec!["completion_a", "completion_b"],
7135//     );
7136//     handle_copilot_completion_request(
7137//         &copilot_lsp,
7138//         vec![copilot::request::Completion {
7139//             text: "one.copilot1".into(),
7140//             range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 4)),
7141//             ..Default::default()
7142//         }],
7143//         vec![],
7144//     );
7145//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7146//     cx.update_editor(|editor, cx| {
7147//         assert!(editor.context_menu_visible());
7148//         assert!(!editor.has_active_copilot_suggestion(cx));
7149
7150//         // When hiding the context menu, the Copilot suggestion becomes visible.
7151//         editor.hide_context_menu(cx);
7152//         assert!(!editor.context_menu_visible());
7153//         assert!(editor.has_active_copilot_suggestion(cx));
7154//         assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
7155//         assert_eq!(editor.text(cx), "one.\ntwo\nthree\n");
7156//     });
7157
7158//     // Ensure existing completion is interpolated when inserting again.
7159//     cx.simulate_keystroke("c");
7160//     deterministic.run_until_parked();
7161//     cx.update_editor(|editor, cx| {
7162//         assert!(!editor.context_menu_visible());
7163//         assert!(editor.has_active_copilot_suggestion(cx));
7164//         assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
7165//         assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
7166//     });
7167
7168//     // After debouncing, new Copilot completions should be requested.
7169//     handle_copilot_completion_request(
7170//         &copilot_lsp,
7171//         vec![copilot::request::Completion {
7172//             text: "one.copilot2".into(),
7173//             range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 5)),
7174//             ..Default::default()
7175//         }],
7176//         vec![],
7177//     );
7178//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7179//     cx.update_editor(|editor, cx| {
7180//         assert!(!editor.context_menu_visible());
7181//         assert!(editor.has_active_copilot_suggestion(cx));
7182//         assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
7183//         assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
7184
7185//         // Canceling should remove the active Copilot suggestion.
7186//         editor.cancel(&Default::default(), cx);
7187//         assert!(!editor.has_active_copilot_suggestion(cx));
7188//         assert_eq!(editor.display_text(cx), "one.c\ntwo\nthree\n");
7189//         assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
7190
7191//         // After canceling, tabbing shouldn't insert the previously shown suggestion.
7192//         editor.tab(&Default::default(), cx);
7193//         assert!(!editor.has_active_copilot_suggestion(cx));
7194//         assert_eq!(editor.display_text(cx), "one.c   \ntwo\nthree\n");
7195//         assert_eq!(editor.text(cx), "one.c   \ntwo\nthree\n");
7196
7197//         // When undoing the previously active suggestion is shown again.
7198//         editor.undo(&Default::default(), cx);
7199//         assert!(editor.has_active_copilot_suggestion(cx));
7200//         assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
7201//         assert_eq!(editor.text(cx), "one.c\ntwo\nthree\n");
7202//     });
7203
7204//     // If an edit occurs outside of this editor, the suggestion is still correctly interpolated.
7205//     cx.update_buffer(|buffer, cx| buffer.edit([(5..5, "o")], None, cx));
7206//     cx.update_editor(|editor, cx| {
7207//         assert!(editor.has_active_copilot_suggestion(cx));
7208//         assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
7209//         assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
7210
7211//         // Tabbing when there is an active suggestion inserts it.
7212//         editor.tab(&Default::default(), cx);
7213//         assert!(!editor.has_active_copilot_suggestion(cx));
7214//         assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
7215//         assert_eq!(editor.text(cx), "one.copilot2\ntwo\nthree\n");
7216
7217//         // When undoing the previously active suggestion is shown again.
7218//         editor.undo(&Default::default(), cx);
7219//         assert!(editor.has_active_copilot_suggestion(cx));
7220//         assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
7221//         assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
7222
7223//         // Hide suggestion.
7224//         editor.cancel(&Default::default(), cx);
7225//         assert!(!editor.has_active_copilot_suggestion(cx));
7226//         assert_eq!(editor.display_text(cx), "one.co\ntwo\nthree\n");
7227//         assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
7228//     });
7229
7230//     // If an edit occurs outside of this editor but no suggestion is being shown,
7231//     // we won't make it visible.
7232//     cx.update_buffer(|buffer, cx| buffer.edit([(6..6, "p")], None, cx));
7233//     cx.update_editor(|editor, cx| {
7234//         assert!(!editor.has_active_copilot_suggestion(cx));
7235//         assert_eq!(editor.display_text(cx), "one.cop\ntwo\nthree\n");
7236//         assert_eq!(editor.text(cx), "one.cop\ntwo\nthree\n");
7237//     });
7238
7239//     // Reset the editor to verify how suggestions behave when tabbing on leading indentation.
7240//     cx.update_editor(|editor, cx| {
7241//         editor.set_text("fn foo() {\n  \n}", cx);
7242//         editor.change_selections(None, cx, |s| {
7243//             s.select_ranges([Point::new(1, 2)..Point::new(1, 2)])
7244//         });
7245//     });
7246//     handle_copilot_completion_request(
7247//         &copilot_lsp,
7248//         vec![copilot::request::Completion {
7249//             text: "    let x = 4;".into(),
7250//             range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 2)),
7251//             ..Default::default()
7252//         }],
7253//         vec![],
7254//     );
7255
7256//     cx.update_editor(|editor, cx| editor.next_copilot_suggestion(&Default::default(), cx));
7257//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7258//     cx.update_editor(|editor, cx| {
7259//         assert!(editor.has_active_copilot_suggestion(cx));
7260//         assert_eq!(editor.display_text(cx), "fn foo() {\n    let x = 4;\n}");
7261//         assert_eq!(editor.text(cx), "fn foo() {\n  \n}");
7262
7263//         // Tabbing inside of leading whitespace inserts indentation without accepting the suggestion.
7264//         editor.tab(&Default::default(), cx);
7265//         assert!(editor.has_active_copilot_suggestion(cx));
7266//         assert_eq!(editor.text(cx), "fn foo() {\n    \n}");
7267//         assert_eq!(editor.display_text(cx), "fn foo() {\n    let x = 4;\n}");
7268
7269//         // Tabbing again accepts the suggestion.
7270//         editor.tab(&Default::default(), cx);
7271//         assert!(!editor.has_active_copilot_suggestion(cx));
7272//         assert_eq!(editor.text(cx), "fn foo() {\n    let x = 4;\n}");
7273//         assert_eq!(editor.display_text(cx), "fn foo() {\n    let x = 4;\n}");
7274//     });
7275// }
7276
7277// #[gpui::test]
7278// async fn test_copilot_completion_invalidation(
7279//     deterministic: Arc<Deterministic>,
7280//     cx: &mut gpui::TestAppContext,
7281// ) {
7282//     init_test(cx, |_| {});
7283
7284//     let (copilot, copilot_lsp) = Copilot::fake(cx);
7285//     cx.update(|cx| cx.set_global(copilot));
7286//     let mut cx = EditorLspTestContext::new_rust(
7287//         lsp::ServerCapabilities {
7288//             completion_provider: Some(lsp::CompletionOptions {
7289//                 trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
7290//                 ..Default::default()
7291//             }),
7292//             ..Default::default()
7293//         },
7294//         cx,
7295//     )
7296//     .await;
7297
7298//     cx.set_state(indoc! {"
7299//         one
7300//         twˇ
7301//         three
7302//     "});
7303
7304//     handle_copilot_completion_request(
7305//         &copilot_lsp,
7306//         vec![copilot::request::Completion {
7307//             text: "two.foo()".into(),
7308//             range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 2)),
7309//             ..Default::default()
7310//         }],
7311//         vec![],
7312//     );
7313//     cx.update_editor(|editor, cx| editor.next_copilot_suggestion(&Default::default(), cx));
7314//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7315//     cx.update_editor(|editor, cx| {
7316//         assert!(editor.has_active_copilot_suggestion(cx));
7317//         assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
7318//         assert_eq!(editor.text(cx), "one\ntw\nthree\n");
7319
7320//         editor.backspace(&Default::default(), cx);
7321//         assert!(editor.has_active_copilot_suggestion(cx));
7322//         assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
7323//         assert_eq!(editor.text(cx), "one\nt\nthree\n");
7324
7325//         editor.backspace(&Default::default(), cx);
7326//         assert!(editor.has_active_copilot_suggestion(cx));
7327//         assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
7328//         assert_eq!(editor.text(cx), "one\n\nthree\n");
7329
7330//         // Deleting across the original suggestion range invalidates it.
7331//         editor.backspace(&Default::default(), cx);
7332//         assert!(!editor.has_active_copilot_suggestion(cx));
7333//         assert_eq!(editor.display_text(cx), "one\nthree\n");
7334//         assert_eq!(editor.text(cx), "one\nthree\n");
7335
7336//         // Undoing the deletion restores the suggestion.
7337//         editor.undo(&Default::default(), cx);
7338//         assert!(editor.has_active_copilot_suggestion(cx));
7339//         assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n");
7340//         assert_eq!(editor.text(cx), "one\n\nthree\n");
7341//     });
7342// }
7343
7344// #[gpui::test]
7345// async fn test_copilot_multibuffer(
7346//     deterministic: Arc<Deterministic>,
7347//     cx: &mut gpui::TestAppContext,
7348// ) {
7349//     init_test(cx, |_| {});
7350
7351//     let (copilot, copilot_lsp) = Copilot::fake(cx);
7352//     cx.update(|cx| cx.set_global(copilot));
7353
7354//     let buffer_1 = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "a = 1\nb = 2\n"));
7355//     let buffer_2 = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "c = 3\nd = 4\n"));
7356//     let multibuffer = cx.add_model(|cx| {
7357//         let mut multibuffer = MultiBuffer::new(0);
7358//         multibuffer.push_excerpts(
7359//             buffer_1.clone(),
7360//             [ExcerptRange {
7361//                 context: Point::new(0, 0)..Point::new(2, 0),
7362//                 primary: None,
7363//             }],
7364//             cx,
7365//         );
7366//         multibuffer.push_excerpts(
7367//             buffer_2.clone(),
7368//             [ExcerptRange {
7369//                 context: Point::new(0, 0)..Point::new(2, 0),
7370//                 primary: None,
7371//             }],
7372//             cx,
7373//         );
7374//         multibuffer
7375//     });
7376//     let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
7377
7378//     handle_copilot_completion_request(
7379//         &copilot_lsp,
7380//         vec![copilot::request::Completion {
7381//             text: "b = 2 + a".into(),
7382//             range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 5)),
7383//             ..Default::default()
7384//         }],
7385//         vec![],
7386//     );
7387//     editor.update(cx, |editor, cx| {
7388//         // Ensure copilot suggestions are shown for the first excerpt.
7389//         editor.change_selections(None, cx, |s| {
7390//             s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
7391//         });
7392//         editor.next_copilot_suggestion(&Default::default(), cx);
7393//     });
7394//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7395//     editor.update(cx, |editor, cx| {
7396//         assert!(editor.has_active_copilot_suggestion(cx));
7397//         assert_eq!(
7398//             editor.display_text(cx),
7399//             "\n\na = 1\nb = 2 + a\n\n\n\nc = 3\nd = 4\n"
7400//         );
7401//         assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
7402//     });
7403
7404//     handle_copilot_completion_request(
7405//         &copilot_lsp,
7406//         vec![copilot::request::Completion {
7407//             text: "d = 4 + c".into(),
7408//             range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 6)),
7409//             ..Default::default()
7410//         }],
7411//         vec![],
7412//     );
7413//     editor.update(cx, |editor, cx| {
7414//         // Move to another excerpt, ensuring the suggestion gets cleared.
7415//         editor.change_selections(None, cx, |s| {
7416//             s.select_ranges([Point::new(4, 5)..Point::new(4, 5)])
7417//         });
7418//         assert!(!editor.has_active_copilot_suggestion(cx));
7419//         assert_eq!(
7420//             editor.display_text(cx),
7421//             "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4\n"
7422//         );
7423//         assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
7424
7425//         // Type a character, ensuring we don't even try to interpolate the previous suggestion.
7426//         editor.handle_input(" ", cx);
7427//         assert!(!editor.has_active_copilot_suggestion(cx));
7428//         assert_eq!(
7429//             editor.display_text(cx),
7430//             "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 \n"
7431//         );
7432//         assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
7433//     });
7434
7435//     // Ensure the new suggestion is displayed when the debounce timeout expires.
7436//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7437//     editor.update(cx, |editor, cx| {
7438//         assert!(editor.has_active_copilot_suggestion(cx));
7439//         assert_eq!(
7440//             editor.display_text(cx),
7441//             "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 + c\n"
7442//         );
7443//         assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
7444//     });
7445// }
7446
7447// #[gpui::test]
7448// async fn test_copilot_disabled_globs(
7449//     deterministic: Arc<Deterministic>,
7450//     cx: &mut gpui::TestAppContext,
7451// ) {
7452//     init_test(cx, |settings| {
7453//         settings
7454//             .copilot
7455//             .get_or_insert(Default::default())
7456//             .disabled_globs = Some(vec![".env*".to_string()]);
7457//     });
7458
7459//     let (copilot, copilot_lsp) = Copilot::fake(cx);
7460//     cx.update(|cx| cx.set_global(copilot));
7461
7462//     let fs = FakeFs::new(cx.background());
7463//     fs.insert_tree(
7464//         "/test",
7465//         json!({
7466//             ".env": "SECRET=something\n",
7467//             "README.md": "hello\n"
7468//         }),
7469//     )
7470//     .await;
7471//     let project = Project::test(fs, ["/test".as_ref()], cx).await;
7472
7473//     let private_buffer = project
7474//         .update(cx, |project, cx| {
7475//             project.open_local_buffer("/test/.env", cx)
7476//         })
7477//         .await
7478//         .unwrap();
7479//     let public_buffer = project
7480//         .update(cx, |project, cx| {
7481//             project.open_local_buffer("/test/README.md", cx)
7482//         })
7483//         .await
7484//         .unwrap();
7485
7486//     let multibuffer = cx.add_model(|cx| {
7487//         let mut multibuffer = MultiBuffer::new(0);
7488//         multibuffer.push_excerpts(
7489//             private_buffer.clone(),
7490//             [ExcerptRange {
7491//                 context: Point::new(0, 0)..Point::new(1, 0),
7492//                 primary: None,
7493//             }],
7494//             cx,
7495//         );
7496//         multibuffer.push_excerpts(
7497//             public_buffer.clone(),
7498//             [ExcerptRange {
7499//                 context: Point::new(0, 0)..Point::new(1, 0),
7500//                 primary: None,
7501//             }],
7502//             cx,
7503//         );
7504//         multibuffer
7505//     });
7506//     let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
7507
7508//     let mut copilot_requests = copilot_lsp
7509//         .handle_request::<copilot::request::GetCompletions, _, _>(move |_params, _cx| async move {
7510//             Ok(copilot::request::GetCompletionsResult {
7511//                 completions: vec![copilot::request::Completion {
7512//                     text: "next line".into(),
7513//                     range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 0)),
7514//                     ..Default::default()
7515//                 }],
7516//             })
7517//         });
7518
7519//     editor.update(cx, |editor, cx| {
7520//         editor.change_selections(None, cx, |selections| {
7521//             selections.select_ranges([Point::new(0, 0)..Point::new(0, 0)])
7522//         });
7523//         editor.next_copilot_suggestion(&Default::default(), cx);
7524//     });
7525
7526//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7527//     assert!(copilot_requests.try_next().is_err());
7528
7529//     editor.update(cx, |editor, cx| {
7530//         editor.change_selections(None, cx, |s| {
7531//             s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
7532//         });
7533//         editor.next_copilot_suggestion(&Default::default(), cx);
7534//     });
7535
7536//     deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
7537//     assert!(copilot_requests.try_next().is_ok());
7538// }
7539
7540// #[gpui::test]
7541// async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) {
7542//     init_test(cx, |_| {});
7543
7544//     let mut language = Language::new(
7545//         LanguageConfig {
7546//             name: "Rust".into(),
7547//             path_suffixes: vec!["rs".to_string()],
7548//             brackets: BracketPairConfig {
7549//                 pairs: vec![BracketPair {
7550//                     start: "{".to_string(),
7551//                     end: "}".to_string(),
7552//                     close: true,
7553//                     newline: true,
7554//                 }],
7555//                 disabled_scopes_by_bracket_ix: Vec::new(),
7556//             },
7557//             ..Default::default()
7558//         },
7559//         Some(tree_sitter_rust::language()),
7560//     );
7561//     let mut fake_servers = language
7562//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
7563//             capabilities: lsp::ServerCapabilities {
7564//                 document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
7565//                     first_trigger_character: "{".to_string(),
7566//                     more_trigger_character: None,
7567//                 }),
7568//                 ..Default::default()
7569//             },
7570//             ..Default::default()
7571//         }))
7572//         .await;
7573
7574//     let fs = FakeFs::new(cx.background());
7575//     fs.insert_tree(
7576//         "/a",
7577//         json!({
7578//             "main.rs": "fn main() { let a = 5; }",
7579//             "other.rs": "// Test file",
7580//         }),
7581//     )
7582//     .await;
7583//     let project = Project::test(fs, ["/a".as_ref()], cx).await;
7584//     project.update(cx, |project, _| project.languages().add(Arc::new(language)));
7585//     let workspace = cx
7586//         .add_window(|cx| Workspace::test_new(project.clone(), cx))
7587//         .root(cx);
7588//     let worktree_id = workspace.update(cx, |workspace, cx| {
7589//         workspace.project().read_with(cx, |project, cx| {
7590//             project.worktrees(cx).next().unwrap().read(cx).id()
7591//         })
7592//     });
7593
7594//     let buffer = project
7595//         .update(cx, |project, cx| {
7596//             project.open_local_buffer("/a/main.rs", cx)
7597//         })
7598//         .await
7599//         .unwrap();
7600//     cx.foreground().run_until_parked();
7601//     cx.foreground().start_waiting();
7602//     let fake_server = fake_servers.next().await.unwrap();
7603//     let editor_handle = workspace
7604//         .update(cx, |workspace, cx| {
7605//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
7606//         })
7607//         .await
7608//         .unwrap()
7609//         .downcast::<Editor>()
7610//         .unwrap();
7611
7612//     fake_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
7613//         assert_eq!(
7614//             params.text_document_position.text_document.uri,
7615//             lsp::Url::from_file_path("/a/main.rs").unwrap(),
7616//         );
7617//         assert_eq!(
7618//             params.text_document_position.position,
7619//             lsp::Position::new(0, 21),
7620//         );
7621
7622//         Ok(Some(vec![lsp::TextEdit {
7623//             new_text: "]".to_string(),
7624//             range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
7625//         }]))
7626//     });
7627
7628//     editor_handle.update(cx, |editor, cx| {
7629//         cx.focus(&editor_handle);
7630//         editor.change_selections(None, cx, |s| {
7631//             s.select_ranges([Point::new(0, 21)..Point::new(0, 20)])
7632//         });
7633//         editor.handle_input("{", cx);
7634//     });
7635
7636//     cx.foreground().run_until_parked();
7637
7638//     buffer.read_with(cx, |buffer, _| {
7639//         assert_eq!(
7640//             buffer.text(),
7641//             "fn main() { let a = {5}; }",
7642//             "No extra braces from on type formatting should appear in the buffer"
7643//         )
7644//     });
7645// }
7646
7647// #[gpui::test]
7648// async fn test_language_server_restart_due_to_settings_change(cx: &mut gpui::TestAppContext) {
7649//     init_test(cx, |_| {});
7650
7651//     let language_name: Arc<str> = "Rust".into();
7652//     let mut language = Language::new(
7653//         LanguageConfig {
7654//             name: Arc::clone(&language_name),
7655//             path_suffixes: vec!["rs".to_string()],
7656//             ..Default::default()
7657//         },
7658//         Some(tree_sitter_rust::language()),
7659//     );
7660
7661//     let server_restarts = Arc::new(AtomicUsize::new(0));
7662//     let closure_restarts = Arc::clone(&server_restarts);
7663//     let language_server_name = "test language server";
7664//     let mut fake_servers = language
7665//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
7666//             name: language_server_name,
7667//             initialization_options: Some(json!({
7668//                 "testOptionValue": true
7669//             })),
7670//             initializer: Some(Box::new(move |fake_server| {
7671//                 let task_restarts = Arc::clone(&closure_restarts);
7672//                 fake_server.handle_request::<lsp::request::Shutdown, _, _>(move |_, _| {
7673//                     task_restarts.fetch_add(1, atomic::Ordering::Release);
7674//                     futures::future::ready(Ok(()))
7675//                 });
7676//             })),
7677//             ..Default::default()
7678//         }))
7679//         .await;
7680
7681//     let fs = FakeFs::new(cx.background());
7682//     fs.insert_tree(
7683//         "/a",
7684//         json!({
7685//             "main.rs": "fn main() { let a = 5; }",
7686//             "other.rs": "// Test file",
7687//         }),
7688//     )
7689//     .await;
7690//     let project = Project::test(fs, ["/a".as_ref()], cx).await;
7691//     project.update(cx, |project, _| project.languages().add(Arc::new(language)));
7692//     let _window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
7693//     let _buffer = project
7694//         .update(cx, |project, cx| {
7695//             project.open_local_buffer("/a/main.rs", cx)
7696//         })
7697//         .await
7698//         .unwrap();
7699//     let _fake_server = fake_servers.next().await.unwrap();
7700//     update_test_language_settings(cx, |language_settings| {
7701//         language_settings.languages.insert(
7702//             Arc::clone(&language_name),
7703//             LanguageSettingsContent {
7704//                 tab_size: NonZeroU32::new(8),
7705//                 ..Default::default()
7706//             },
7707//         );
7708//     });
7709//     cx.foreground().run_until_parked();
7710//     assert_eq!(
7711//         server_restarts.load(atomic::Ordering::Acquire),
7712//         0,
7713//         "Should not restart LSP server on an unrelated change"
7714//     );
7715
7716//     update_test_project_settings(cx, |project_settings| {
7717//         project_settings.lsp.insert(
7718//             "Some other server name".into(),
7719//             LspSettings {
7720//                 initialization_options: Some(json!({
7721//                     "some other init value": false
7722//                 })),
7723//             },
7724//         );
7725//     });
7726//     cx.foreground().run_until_parked();
7727//     assert_eq!(
7728//         server_restarts.load(atomic::Ordering::Acquire),
7729//         0,
7730//         "Should not restart LSP server on an unrelated LSP settings change"
7731//     );
7732
7733//     update_test_project_settings(cx, |project_settings| {
7734//         project_settings.lsp.insert(
7735//             language_server_name.into(),
7736//             LspSettings {
7737//                 initialization_options: Some(json!({
7738//                     "anotherInitValue": false
7739//                 })),
7740//             },
7741//         );
7742//     });
7743//     cx.foreground().run_until_parked();
7744//     assert_eq!(
7745//         server_restarts.load(atomic::Ordering::Acquire),
7746//         1,
7747//         "Should restart LSP server on a related LSP settings change"
7748//     );
7749
7750//     update_test_project_settings(cx, |project_settings| {
7751//         project_settings.lsp.insert(
7752//             language_server_name.into(),
7753//             LspSettings {
7754//                 initialization_options: Some(json!({
7755//                     "anotherInitValue": false
7756//                 })),
7757//             },
7758//         );
7759//     });
7760//     cx.foreground().run_until_parked();
7761//     assert_eq!(
7762//         server_restarts.load(atomic::Ordering::Acquire),
7763//         1,
7764//         "Should not restart LSP server on a related LSP settings change that is the same"
7765//     );
7766
7767//     update_test_project_settings(cx, |project_settings| {
7768//         project_settings.lsp.insert(
7769//             language_server_name.into(),
7770//             LspSettings {
7771//                 initialization_options: None,
7772//             },
7773//         );
7774//     });
7775//     cx.foreground().run_until_parked();
7776//     assert_eq!(
7777//         server_restarts.load(atomic::Ordering::Acquire),
7778//         2,
7779//         "Should restart LSP server on another related LSP settings change"
7780//     );
7781// }
7782
7783// #[gpui::test]
7784// async fn test_completions_with_additional_edits(cx: &mut gpui::TestAppContext) {
7785//     init_test(cx, |_| {});
7786
7787//     let mut cx = EditorLspTestContext::new_rust(
7788//         lsp::ServerCapabilities {
7789//             completion_provider: Some(lsp::CompletionOptions {
7790//                 trigger_characters: Some(vec![".".to_string()]),
7791//                 resolve_provider: Some(true),
7792//                 ..Default::default()
7793//             }),
7794//             ..Default::default()
7795//         },
7796//         cx,
7797//     )
7798//     .await;
7799
7800//     cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
7801//     cx.simulate_keystroke(".");
7802//     let completion_item = lsp::CompletionItem {
7803//         label: "some".into(),
7804//         kind: Some(lsp::CompletionItemKind::SNIPPET),
7805//         detail: Some("Wrap the expression in an `Option::Some`".to_string()),
7806//         documentation: Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
7807//             kind: lsp::MarkupKind::Markdown,
7808//             value: "```rust\nSome(2)\n```".to_string(),
7809//         })),
7810//         deprecated: Some(false),
7811//         sort_text: Some("fffffff2".to_string()),
7812//         filter_text: Some("some".to_string()),
7813//         insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
7814//         text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
7815//             range: lsp::Range {
7816//                 start: lsp::Position {
7817//                     line: 0,
7818//                     character: 22,
7819//                 },
7820//                 end: lsp::Position {
7821//                     line: 0,
7822//                     character: 22,
7823//                 },
7824//             },
7825//             new_text: "Some(2)".to_string(),
7826//         })),
7827//         additional_text_edits: Some(vec![lsp::TextEdit {
7828//             range: lsp::Range {
7829//                 start: lsp::Position {
7830//                     line: 0,
7831//                     character: 20,
7832//                 },
7833//                 end: lsp::Position {
7834//                     line: 0,
7835//                     character: 22,
7836//                 },
7837//             },
7838//             new_text: "".to_string(),
7839//         }]),
7840//         ..Default::default()
7841//     };
7842
7843//     let closure_completion_item = completion_item.clone();
7844//     let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
7845//         let task_completion_item = closure_completion_item.clone();
7846//         async move {
7847//             Ok(Some(lsp::CompletionResponse::Array(vec![
7848//                 task_completion_item,
7849//             ])))
7850//         }
7851//     });
7852
7853//     request.next().await;
7854
7855//     cx.condition(|editor, _| editor.context_menu_visible())
7856//         .await;
7857//     let apply_additional_edits = cx.update_editor(|editor, cx| {
7858//         editor
7859//             .confirm_completion(&ConfirmCompletion::default(), cx)
7860//             .unwrap()
7861//     });
7862//     cx.assert_editor_state(indoc! {"fn main() { let a = 2.Some(2)ˇ; }"});
7863
7864//     cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
7865//         let task_completion_item = completion_item.clone();
7866//         async move { Ok(task_completion_item) }
7867//     })
7868//     .next()
7869//     .await
7870//     .unwrap();
7871//     apply_additional_edits.await.unwrap();
7872//     cx.assert_editor_state(indoc! {"fn main() { let a = Some(2)ˇ; }"});
7873// }
7874
7875// #[gpui::test]
7876// async fn test_completions_in_languages_with_extra_word_characters(cx: &mut gpui::TestAppContext) {
7877//     init_test(cx, |_| {});
7878
7879//     let mut cx = EditorLspTestContext::new(
7880//         Language::new(
7881//             LanguageConfig {
7882//                 path_suffixes: vec!["jsx".into()],
7883//                 overrides: [(
7884//                     "element".into(),
7885//                     LanguageConfigOverride {
7886//                         word_characters: Override::Set(['-'].into_iter().collect()),
7887//                         ..Default::default()
7888//                     },
7889//                 )]
7890//                 .into_iter()
7891//                 .collect(),
7892//                 ..Default::default()
7893//             },
7894//             Some(tree_sitter_typescript::language_tsx()),
7895//         )
7896//         .with_override_query("(jsx_self_closing_element) @element")
7897//         .unwrap(),
7898//         lsp::ServerCapabilities {
7899//             completion_provider: Some(lsp::CompletionOptions {
7900//                 trigger_characters: Some(vec![":".to_string()]),
7901//                 ..Default::default()
7902//             }),
7903//             ..Default::default()
7904//         },
7905//         cx,
7906//     )
7907//     .await;
7908
7909//     cx.lsp
7910//         .handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
7911//             Ok(Some(lsp::CompletionResponse::Array(vec![
7912//                 lsp::CompletionItem {
7913//                     label: "bg-blue".into(),
7914//                     ..Default::default()
7915//                 },
7916//                 lsp::CompletionItem {
7917//                     label: "bg-red".into(),
7918//                     ..Default::default()
7919//                 },
7920//                 lsp::CompletionItem {
7921//                     label: "bg-yellow".into(),
7922//                     ..Default::default()
7923//                 },
7924//             ])))
7925//         });
7926
7927//     cx.set_state(r#"<p class="bgˇ" />"#);
7928
7929//     // Trigger completion when typing a dash, because the dash is an extra
7930//     // word character in the 'element' scope, which contains the cursor.
7931//     cx.simulate_keystroke("-");
7932//     cx.foreground().run_until_parked();
7933//     cx.update_editor(|editor, _| {
7934//         if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
7935//             assert_eq!(
7936//                 menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
7937//                 &["bg-red", "bg-blue", "bg-yellow"]
7938//             );
7939//         } else {
7940//             panic!("expected completion menu to be open");
7941//         }
7942//     });
7943
7944//     cx.simulate_keystroke("l");
7945//     cx.foreground().run_until_parked();
7946//     cx.update_editor(|editor, _| {
7947//         if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
7948//             assert_eq!(
7949//                 menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
7950//                 &["bg-blue", "bg-yellow"]
7951//             );
7952//         } else {
7953//             panic!("expected completion menu to be open");
7954//         }
7955//     });
7956
7957//     // When filtering completions, consider the character after the '-' to
7958//     // be the start of a subword.
7959//     cx.set_state(r#"<p class="yelˇ" />"#);
7960//     cx.simulate_keystroke("l");
7961//     cx.foreground().run_until_parked();
7962//     cx.update_editor(|editor, _| {
7963//         if let Some(ContextMenu::Completions(menu)) = editor.context_menu.read().as_ref() {
7964//             assert_eq!(
7965//                 menu.matches.iter().map(|m| &m.string).collect::<Vec<_>>(),
7966//                 &["bg-yellow"]
7967//             );
7968//         } else {
7969//             panic!("expected completion menu to be open");
7970//         }
7971//     });
7972// }
7973
7974// #[gpui::test]
7975// async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
7976//     init_test(cx, |settings| {
7977//         settings.defaults.formatter = Some(language_settings::Formatter::Prettier)
7978//     });
7979
7980//     let mut language = Language::new(
7981//         LanguageConfig {
7982//             name: "Rust".into(),
7983//             path_suffixes: vec!["rs".to_string()],
7984//             prettier_parser_name: Some("test_parser".to_string()),
7985//             ..Default::default()
7986//         },
7987//         Some(tree_sitter_rust::language()),
7988//     );
7989
7990//     let test_plugin = "test_plugin";
7991//     let _ = language
7992//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
7993//             prettier_plugins: vec![test_plugin],
7994//             ..Default::default()
7995//         }))
7996//         .await;
7997
7998//     let fs = FakeFs::new(cx.background());
7999//     fs.insert_file("/file.rs", Default::default()).await;
8000
8001//     let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
8002//     let prettier_format_suffix = project::TEST_PRETTIER_FORMAT_SUFFIX;
8003//     project.update(cx, |project, _| {
8004//         project.languages().add(Arc::new(language));
8005//     });
8006//     let buffer = project
8007//         .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
8008//         .await
8009//         .unwrap();
8010
8011//     let buffer_text = "one\ntwo\nthree\n";
8012//     let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8013//     let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
8014//     editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx));
8015
8016//     let format = editor.update(cx, |editor, cx| {
8017//         editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
8018//     });
8019//     format.await.unwrap();
8020//     assert_eq!(
8021//         editor.read_with(cx, |editor, cx| editor.text(cx)),
8022//         buffer_text.to_string() + prettier_format_suffix,
8023//         "Test prettier formatting was not applied to the original buffer text",
8024//     );
8025
8026//     update_test_language_settings(cx, |settings| {
8027//         settings.defaults.formatter = Some(language_settings::Formatter::Auto)
8028//     });
8029//     let format = editor.update(cx, |editor, cx| {
8030//         editor.perform_format(project.clone(), FormatTrigger::Manual, cx)
8031//     });
8032//     format.await.unwrap();
8033//     assert_eq!(
8034//         editor.read_with(cx, |editor, cx| editor.text(cx)),
8035//         buffer_text.to_string() + prettier_format_suffix + "\n" + prettier_format_suffix,
8036//         "Autoformatting (via test prettier) was not applied to the original buffer text",
8037//     );
8038// }
8039
8040// fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
8041//     let point = DisplayPoint::new(row as u32, column as u32);
8042//     point..point
8043// }
8044
8045// fn assert_selection_ranges(marked_text: &str, view: &mut Editor, cx: &mut ViewContext<Editor>) {
8046//     let (text, ranges) = marked_text_ranges(marked_text, true);
8047//     assert_eq!(view.text(cx), text);
8048//     assert_eq!(
8049//         view.selections.ranges(cx),
8050//         ranges,
8051//         "Assert selections are {}",
8052//         marked_text
8053//     );
8054// }
8055
8056// /// Handle completion request passing a marked string specifying where the completion
8057// /// should be triggered from using '|' character, what range should be replaced, and what completions
8058// /// should be returned using '<' and '>' to delimit the range
8059// pub fn handle_completion_request<'a>(
8060//     cx: &mut EditorLspTestContext<'a>,
8061//     marked_string: &str,
8062//     completions: Vec<&'static str>,
8063// ) -> impl Future<Output = ()> {
8064//     let complete_from_marker: TextRangeMarker = '|'.into();
8065//     let replace_range_marker: TextRangeMarker = ('<', '>').into();
8066//     let (_, mut marked_ranges) = marked_text_ranges_by(
8067//         marked_string,
8068//         vec![complete_from_marker.clone(), replace_range_marker.clone()],
8069//     );
8070
8071//     let complete_from_position =
8072//         cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
8073//     let replace_range =
8074//         cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
8075
8076//     let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
8077//         let completions = completions.clone();
8078//         async move {
8079//             assert_eq!(params.text_document_position.text_document.uri, url.clone());
8080//             assert_eq!(
8081//                 params.text_document_position.position,
8082//                 complete_from_position
8083//             );
8084//             Ok(Some(lsp::CompletionResponse::Array(
8085//                 completions
8086//                     .iter()
8087//                     .map(|completion_text| lsp::CompletionItem {
8088//                         label: completion_text.to_string(),
8089//                         text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
8090//                             range: replace_range,
8091//                             new_text: completion_text.to_string(),
8092//                         })),
8093//                         ..Default::default()
8094//                     })
8095//                     .collect(),
8096//             )))
8097//         }
8098//     });
8099
8100//     async move {
8101//         request.next().await;
8102//     }
8103// }
8104
8105// fn handle_resolve_completion_request<'a>(
8106//     cx: &mut EditorLspTestContext<'a>,
8107//     edits: Option<Vec<(&'static str, &'static str)>>,
8108// ) -> impl Future<Output = ()> {
8109//     let edits = edits.map(|edits| {
8110//         edits
8111//             .iter()
8112//             .map(|(marked_string, new_text)| {
8113//                 let (_, marked_ranges) = marked_text_ranges(marked_string, false);
8114//                 let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
8115//                 lsp::TextEdit::new(replace_range, new_text.to_string())
8116//             })
8117//             .collect::<Vec<_>>()
8118//     });
8119
8120//     let mut request =
8121//         cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
8122//             let edits = edits.clone();
8123//             async move {
8124//                 Ok(lsp::CompletionItem {
8125//                     additional_text_edits: edits,
8126//                     ..Default::default()
8127//                 })
8128//             }
8129//         });
8130
8131//     async move {
8132//         request.next().await;
8133//     }
8134// }
8135
8136// fn handle_copilot_completion_request(
8137//     lsp: &lsp::FakeLanguageServer,
8138//     completions: Vec<copilot::request::Completion>,
8139//     completions_cycling: Vec<copilot::request::Completion>,
8140// ) {
8141//     lsp.handle_request::<copilot::request::GetCompletions, _, _>(move |_params, _cx| {
8142//         let completions = completions.clone();
8143//         async move {
8144//             Ok(copilot::request::GetCompletionsResult {
8145//                 completions: completions.clone(),
8146//             })
8147//         }
8148//     });
8149//     lsp.handle_request::<copilot::request::GetCompletionsCycling, _, _>(move |_params, _cx| {
8150//         let completions_cycling = completions_cycling.clone();
8151//         async move {
8152//             Ok(copilot::request::GetCompletionsResult {
8153//                 completions: completions_cycling.clone(),
8154//             })
8155//         }
8156//     });
8157// }
8158
8159pub(crate) fn update_test_language_settings(
8160    cx: &mut TestAppContext,
8161    f: impl Fn(&mut AllLanguageSettingsContent),
8162) {
8163    cx.update(|cx| {
8164        cx.update_global::<SettingsStore, _>(|store, cx| {
8165            store.update_user_settings::<AllLanguageSettings>(cx, f);
8166        });
8167    });
8168}
8169
8170// pub(crate) fn update_test_project_settings(
8171//     cx: &mut TestAppContext,
8172//     f: impl Fn(&mut ProjectSettings),
8173// ) {
8174//     cx.update(|cx| {
8175//         cx.update_global::<SettingsStore, _, _>(|store, cx| {
8176//             store.update_user_settings::<ProjectSettings>(cx, f);
8177//         });
8178//     });
8179// }
8180
8181// pub(crate) fn init_test(cx: &mut TestAppContext, f: fn(&mut AllLanguageSettingsContent)) {
8182//     cx.foreground().forbid_parking();
8183
8184//     cx.update(|cx| {
8185//         cx.set_global(SettingsStore::test(cx));
8186//         theme::init((), cx);
8187//         client::init_settings(cx);
8188//         language::init(cx);
8189//         Project::init_settings(cx);
8190//         workspace::init_settings(cx);
8191//         crate::init(cx);
8192//     });
8193
8194//     update_test_language_settings(cx, f);
8195// }