editor_tests.rs

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