1pub mod display_map;
2mod element;
3pub mod movement;
4
5#[cfg(test)]
6mod test;
7
8use buffer::*;
9use clock::ReplicaId;
10pub use display_map::DisplayPoint;
11use display_map::*;
12pub use element::*;
13use gpui::{
14 action, color::Color, fonts::TextStyle, geometry::vector::Vector2F, keymap::Binding,
15 text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
16 MutableAppContext, RenderContext, View, ViewContext, WeakViewHandle,
17};
18use serde::{Deserialize, Serialize};
19use smallvec::SmallVec;
20use smol::Timer;
21use std::{
22 cell::RefCell,
23 cmp::{self, Ordering},
24 mem,
25 ops::{Range, RangeInclusive},
26 rc::Rc,
27 sync::Arc,
28 time::Duration,
29};
30use sum_tree::Bias;
31use theme::EditorStyle;
32use util::post_inc;
33
34const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
35const MAX_LINE_LEN: usize = 1024;
36
37action!(Cancel);
38action!(Backspace);
39action!(Delete);
40action!(Input, String);
41action!(Tab);
42action!(DeleteLine);
43action!(DeleteToPreviousWordBoundary);
44action!(DeleteToNextWordBoundary);
45action!(DeleteToBeginningOfLine);
46action!(DeleteToEndOfLine);
47action!(CutToEndOfLine);
48action!(DuplicateLine);
49action!(MoveLineUp);
50action!(MoveLineDown);
51action!(Cut);
52action!(Copy);
53action!(Paste);
54action!(Undo);
55action!(Redo);
56action!(MoveUp);
57action!(MoveDown);
58action!(MoveLeft);
59action!(MoveRight);
60action!(MoveToPreviousWordBoundary);
61action!(MoveToNextWordBoundary);
62action!(MoveToBeginningOfLine);
63action!(MoveToEndOfLine);
64action!(MoveToBeginning);
65action!(MoveToEnd);
66action!(SelectUp);
67action!(SelectDown);
68action!(SelectLeft);
69action!(SelectRight);
70action!(SelectToPreviousWordBoundary);
71action!(SelectToNextWordBoundary);
72action!(SelectToBeginningOfLine, bool);
73action!(SelectToEndOfLine);
74action!(SelectToBeginning);
75action!(SelectToEnd);
76action!(SelectAll);
77action!(SelectLine);
78action!(SplitSelectionIntoLines);
79action!(AddSelectionAbove);
80action!(AddSelectionBelow);
81action!(SelectLargerSyntaxNode);
82action!(SelectSmallerSyntaxNode);
83action!(MoveToEnclosingBracket);
84action!(PageUp);
85action!(PageDown);
86action!(Fold);
87action!(Unfold);
88action!(FoldSelectedRanges);
89action!(Scroll, Vector2F);
90action!(Select, SelectPhase);
91
92pub fn init(cx: &mut MutableAppContext) {
93 cx.add_bindings(vec![
94 Binding::new("escape", Cancel, Some("Editor")),
95 Binding::new("backspace", Backspace, Some("Editor")),
96 Binding::new("ctrl-h", Backspace, Some("Editor")),
97 Binding::new("delete", Delete, Some("Editor")),
98 Binding::new("ctrl-d", Delete, Some("Editor")),
99 Binding::new("enter", Input("\n".into()), Some("Editor && mode == full")),
100 Binding::new(
101 "alt-enter",
102 Input("\n".into()),
103 Some("Editor && mode == auto_height"),
104 ),
105 Binding::new("tab", Tab, Some("Editor")),
106 Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")),
107 Binding::new(
108 "alt-backspace",
109 DeleteToPreviousWordBoundary,
110 Some("Editor"),
111 ),
112 Binding::new("alt-h", DeleteToPreviousWordBoundary, Some("Editor")),
113 Binding::new("alt-delete", DeleteToNextWordBoundary, Some("Editor")),
114 Binding::new("alt-d", DeleteToNextWordBoundary, Some("Editor")),
115 Binding::new("cmd-backspace", DeleteToBeginningOfLine, Some("Editor")),
116 Binding::new("cmd-delete", DeleteToEndOfLine, Some("Editor")),
117 Binding::new("ctrl-k", CutToEndOfLine, Some("Editor")),
118 Binding::new("cmd-shift-D", DuplicateLine, Some("Editor")),
119 Binding::new("ctrl-cmd-up", MoveLineUp, Some("Editor")),
120 Binding::new("ctrl-cmd-down", MoveLineDown, Some("Editor")),
121 Binding::new("cmd-x", Cut, Some("Editor")),
122 Binding::new("cmd-c", Copy, Some("Editor")),
123 Binding::new("cmd-v", Paste, Some("Editor")),
124 Binding::new("cmd-z", Undo, Some("Editor")),
125 Binding::new("cmd-shift-Z", Redo, Some("Editor")),
126 Binding::new("up", MoveUp, Some("Editor")),
127 Binding::new("down", MoveDown, Some("Editor")),
128 Binding::new("left", MoveLeft, Some("Editor")),
129 Binding::new("right", MoveRight, Some("Editor")),
130 Binding::new("ctrl-p", MoveUp, Some("Editor")),
131 Binding::new("ctrl-n", MoveDown, Some("Editor")),
132 Binding::new("ctrl-b", MoveLeft, Some("Editor")),
133 Binding::new("ctrl-f", MoveRight, Some("Editor")),
134 Binding::new("alt-left", MoveToPreviousWordBoundary, Some("Editor")),
135 Binding::new("alt-b", MoveToPreviousWordBoundary, Some("Editor")),
136 Binding::new("alt-right", MoveToNextWordBoundary, Some("Editor")),
137 Binding::new("alt-f", MoveToNextWordBoundary, Some("Editor")),
138 Binding::new("cmd-left", MoveToBeginningOfLine, Some("Editor")),
139 Binding::new("ctrl-a", MoveToBeginningOfLine, Some("Editor")),
140 Binding::new("cmd-right", MoveToEndOfLine, Some("Editor")),
141 Binding::new("ctrl-e", MoveToEndOfLine, Some("Editor")),
142 Binding::new("cmd-up", MoveToBeginning, Some("Editor")),
143 Binding::new("cmd-down", MoveToEnd, Some("Editor")),
144 Binding::new("shift-up", SelectUp, Some("Editor")),
145 Binding::new("ctrl-shift-P", SelectUp, Some("Editor")),
146 Binding::new("shift-down", SelectDown, Some("Editor")),
147 Binding::new("ctrl-shift-N", SelectDown, Some("Editor")),
148 Binding::new("shift-left", SelectLeft, Some("Editor")),
149 Binding::new("ctrl-shift-B", SelectLeft, Some("Editor")),
150 Binding::new("shift-right", SelectRight, Some("Editor")),
151 Binding::new("ctrl-shift-F", SelectRight, Some("Editor")),
152 Binding::new(
153 "alt-shift-left",
154 SelectToPreviousWordBoundary,
155 Some("Editor"),
156 ),
157 Binding::new("alt-shift-B", SelectToPreviousWordBoundary, Some("Editor")),
158 Binding::new("alt-shift-right", SelectToNextWordBoundary, Some("Editor")),
159 Binding::new("alt-shift-F", SelectToNextWordBoundary, Some("Editor")),
160 Binding::new(
161 "cmd-shift-left",
162 SelectToBeginningOfLine(true),
163 Some("Editor"),
164 ),
165 Binding::new(
166 "ctrl-shift-A",
167 SelectToBeginningOfLine(true),
168 Some("Editor"),
169 ),
170 Binding::new("cmd-shift-right", SelectToEndOfLine, Some("Editor")),
171 Binding::new("ctrl-shift-E", SelectToEndOfLine, Some("Editor")),
172 Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")),
173 Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")),
174 Binding::new("cmd-a", SelectAll, Some("Editor")),
175 Binding::new("cmd-l", SelectLine, Some("Editor")),
176 Binding::new("cmd-shift-L", SplitSelectionIntoLines, Some("Editor")),
177 Binding::new("cmd-alt-up", AddSelectionAbove, Some("Editor")),
178 Binding::new("cmd-ctrl-p", AddSelectionAbove, Some("Editor")),
179 Binding::new("cmd-alt-down", AddSelectionBelow, Some("Editor")),
180 Binding::new("cmd-ctrl-n", AddSelectionBelow, Some("Editor")),
181 Binding::new("alt-up", SelectLargerSyntaxNode, Some("Editor")),
182 Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")),
183 Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")),
184 Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")),
185 Binding::new("ctrl-m", MoveToEnclosingBracket, Some("Editor")),
186 Binding::new("pageup", PageUp, Some("Editor")),
187 Binding::new("pagedown", PageDown, Some("Editor")),
188 Binding::new("alt-cmd-[", Fold, Some("Editor")),
189 Binding::new("alt-cmd-]", Unfold, Some("Editor")),
190 Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")),
191 ]);
192
193 cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
194 cx.add_action(Editor::select);
195 cx.add_action(Editor::cancel);
196 cx.add_action(Editor::handle_input);
197 cx.add_action(Editor::backspace);
198 cx.add_action(Editor::delete);
199 cx.add_action(Editor::tab);
200 cx.add_action(Editor::delete_line);
201 cx.add_action(Editor::delete_to_previous_word_boundary);
202 cx.add_action(Editor::delete_to_next_word_boundary);
203 cx.add_action(Editor::delete_to_beginning_of_line);
204 cx.add_action(Editor::delete_to_end_of_line);
205 cx.add_action(Editor::cut_to_end_of_line);
206 cx.add_action(Editor::duplicate_line);
207 cx.add_action(Editor::move_line_up);
208 cx.add_action(Editor::move_line_down);
209 cx.add_action(Editor::cut);
210 cx.add_action(Editor::copy);
211 cx.add_action(Editor::paste);
212 cx.add_action(Editor::undo);
213 cx.add_action(Editor::redo);
214 cx.add_action(Editor::move_up);
215 cx.add_action(Editor::move_down);
216 cx.add_action(Editor::move_left);
217 cx.add_action(Editor::move_right);
218 cx.add_action(Editor::move_to_previous_word_boundary);
219 cx.add_action(Editor::move_to_next_word_boundary);
220 cx.add_action(Editor::move_to_beginning_of_line);
221 cx.add_action(Editor::move_to_end_of_line);
222 cx.add_action(Editor::move_to_beginning);
223 cx.add_action(Editor::move_to_end);
224 cx.add_action(Editor::select_up);
225 cx.add_action(Editor::select_down);
226 cx.add_action(Editor::select_left);
227 cx.add_action(Editor::select_right);
228 cx.add_action(Editor::select_to_previous_word_boundary);
229 cx.add_action(Editor::select_to_next_word_boundary);
230 cx.add_action(Editor::select_to_beginning_of_line);
231 cx.add_action(Editor::select_to_end_of_line);
232 cx.add_action(Editor::select_to_beginning);
233 cx.add_action(Editor::select_to_end);
234 cx.add_action(Editor::select_all);
235 cx.add_action(Editor::select_line);
236 cx.add_action(Editor::split_selection_into_lines);
237 cx.add_action(Editor::add_selection_above);
238 cx.add_action(Editor::add_selection_below);
239 cx.add_action(Editor::select_larger_syntax_node);
240 cx.add_action(Editor::select_smaller_syntax_node);
241 cx.add_action(Editor::move_to_enclosing_bracket);
242 cx.add_action(Editor::page_up);
243 cx.add_action(Editor::page_down);
244 cx.add_action(Editor::fold);
245 cx.add_action(Editor::unfold);
246 cx.add_action(Editor::fold_selected_ranges);
247}
248
249trait SelectionExt {
250 fn display_range(&self, map: &DisplayMapSnapshot) -> Range<DisplayPoint>;
251 fn spanned_rows(
252 &self,
253 include_end_if_at_line_start: bool,
254 map: &DisplayMapSnapshot,
255 ) -> SpannedRows;
256}
257
258struct SpannedRows {
259 buffer_rows: Range<u32>,
260 display_rows: Range<u32>,
261}
262
263#[derive(Clone, Debug)]
264pub enum SelectPhase {
265 Begin {
266 position: DisplayPoint,
267 add: bool,
268 },
269 Update {
270 position: DisplayPoint,
271 scroll_position: Vector2F,
272 },
273 End,
274}
275
276#[derive(Copy, Clone, PartialEq, Eq)]
277pub enum EditorMode {
278 SingleLine,
279 AutoHeight { max_lines: usize },
280 Full,
281}
282
283#[derive(Clone)]
284pub struct EditorSettings {
285 pub tab_size: usize,
286 pub style: EditorStyle,
287}
288
289pub struct Editor {
290 handle: WeakViewHandle<Self>,
291 buffer: ModelHandle<Buffer>,
292 display_map: ModelHandle<DisplayMap>,
293 selection_set_id: SelectionSetId,
294 pending_selection: Option<Selection>,
295 next_selection_id: usize,
296 add_selections_state: Option<AddSelectionsState>,
297 autoclose_stack: Vec<AutoclosePairState>,
298 select_larger_syntax_node_stack: Vec<Arc<[Selection]>>,
299 scroll_position: Vector2F,
300 scroll_top_anchor: Anchor,
301 autoscroll_requested: bool,
302 build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
303 focused: bool,
304 show_local_cursors: bool,
305 blink_epoch: usize,
306 blinking_paused: bool,
307 mode: EditorMode,
308 placeholder_text: Option<Arc<str>>,
309}
310
311pub struct Snapshot {
312 pub mode: EditorMode,
313 pub display_snapshot: DisplayMapSnapshot,
314 pub placeholder_text: Option<Arc<str>>,
315 is_focused: bool,
316 scroll_position: Vector2F,
317 scroll_top_anchor: Anchor,
318}
319
320struct AddSelectionsState {
321 above: bool,
322 stack: Vec<usize>,
323}
324
325struct AutoclosePairState {
326 ranges: SmallVec<[Range<Anchor>; 32]>,
327 pair: AutoclosePair,
328}
329
330#[derive(Serialize, Deserialize)]
331struct ClipboardSelection {
332 len: usize,
333 is_entire_line: bool,
334}
335
336impl Editor {
337 pub fn single_line(
338 build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
339 cx: &mut ViewContext<Self>,
340 ) -> Self {
341 let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
342 let mut view = Self::for_buffer(buffer, build_settings, cx);
343 view.mode = EditorMode::SingleLine;
344 view
345 }
346
347 pub fn auto_height(
348 max_lines: usize,
349 build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
350 cx: &mut ViewContext<Self>,
351 ) -> Self {
352 let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
353 let mut view = Self::for_buffer(buffer, build_settings, cx);
354 view.mode = EditorMode::AutoHeight { max_lines };
355 view
356 }
357
358 pub fn for_buffer(
359 buffer: ModelHandle<Buffer>,
360 build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
361 cx: &mut ViewContext<Self>,
362 ) -> Self {
363 Self::new(buffer, Rc::new(RefCell::new(build_settings)), cx)
364 }
365
366 pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
367 let mut clone = Self::new(self.buffer.clone(), self.build_settings.clone(), cx);
368 clone.scroll_position = self.scroll_position;
369 clone.scroll_top_anchor = self.scroll_top_anchor.clone();
370 clone
371 }
372
373 pub fn new(
374 buffer: ModelHandle<Buffer>,
375 build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
376 cx: &mut ViewContext<Self>,
377 ) -> Self {
378 let settings = build_settings.borrow_mut()(cx);
379 let display_map = cx.add_model(|cx| {
380 DisplayMap::new(
381 buffer.clone(),
382 settings.tab_size,
383 settings.style.text.font_id,
384 settings.style.text.font_size,
385 None,
386 cx,
387 )
388 });
389 cx.observe(&buffer, Self::on_buffer_changed).detach();
390 cx.subscribe(&buffer, Self::on_buffer_event).detach();
391 cx.observe(&display_map, Self::on_display_map_changed)
392 .detach();
393
394 let mut next_selection_id = 0;
395 let selection_set_id = buffer.update(cx, |buffer, cx| {
396 buffer.add_selection_set(
397 vec![Selection {
398 id: post_inc(&mut next_selection_id),
399 start: buffer.anchor_before(0),
400 end: buffer.anchor_before(0),
401 reversed: false,
402 goal: SelectionGoal::None,
403 }],
404 cx,
405 )
406 });
407 Self {
408 handle: cx.handle().downgrade(),
409 buffer,
410 display_map,
411 selection_set_id,
412 pending_selection: None,
413 next_selection_id,
414 add_selections_state: None,
415 autoclose_stack: Default::default(),
416 select_larger_syntax_node_stack: Vec::new(),
417 build_settings,
418 scroll_position: Vector2F::zero(),
419 scroll_top_anchor: Anchor::min(),
420 autoscroll_requested: false,
421 focused: false,
422 show_local_cursors: false,
423 blink_epoch: 0,
424 blinking_paused: false,
425 mode: EditorMode::Full,
426 placeholder_text: None,
427 }
428 }
429
430 pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
431 self.buffer.read(cx).replica_id()
432 }
433
434 pub fn buffer(&self) -> &ModelHandle<Buffer> {
435 &self.buffer
436 }
437
438 pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> Snapshot {
439 Snapshot {
440 mode: self.mode,
441 display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
442 scroll_position: self.scroll_position,
443 scroll_top_anchor: self.scroll_top_anchor.clone(),
444 placeholder_text: self.placeholder_text.clone(),
445 is_focused: self
446 .handle
447 .upgrade(cx)
448 .map_or(false, |handle| handle.is_focused(cx)),
449 }
450 }
451
452 pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
453 self.buffer.read(cx).language()
454 }
455
456 pub fn set_placeholder_text(
457 &mut self,
458 placeholder_text: impl Into<Arc<str>>,
459 cx: &mut ViewContext<Self>,
460 ) {
461 self.placeholder_text = Some(placeholder_text.into());
462 cx.notify();
463 }
464
465 fn set_scroll_position(&mut self, mut scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
466 let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
467 let scroll_top_buffer_offset =
468 DisplayPoint::new(scroll_position.y() as u32, 0).to_buffer_offset(&map, Bias::Right);
469 self.scroll_top_anchor = self
470 .buffer
471 .read(cx)
472 .anchor_at(scroll_top_buffer_offset, Bias::Right);
473 scroll_position.set_y(scroll_position.y().fract());
474 self.scroll_position = scroll_position;
475 cx.notify();
476 }
477
478 pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
479 if max < self.scroll_position.x() {
480 self.scroll_position.set_x(max);
481 true
482 } else {
483 false
484 }
485 }
486
487 pub fn autoscroll_vertically(
488 &mut self,
489 viewport_height: f32,
490 line_height: f32,
491 cx: &mut ViewContext<Self>,
492 ) -> bool {
493 let visible_lines = viewport_height / line_height;
494 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
495 let mut scroll_position =
496 compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
497 let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
498 (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
499 } else {
500 display_map.max_point().row().saturating_sub(1) as f32
501 };
502 if scroll_position.y() > max_scroll_top {
503 scroll_position.set_y(max_scroll_top);
504 self.set_scroll_position(scroll_position, cx);
505 }
506
507 if self.autoscroll_requested {
508 self.autoscroll_requested = false;
509 } else {
510 return false;
511 }
512
513 let selections = self.selections(cx);
514 let first_cursor_top = selections
515 .first()
516 .unwrap()
517 .head()
518 .to_display_point(&display_map, Bias::Left)
519 .row() as f32;
520 let last_cursor_bottom = selections
521 .last()
522 .unwrap()
523 .head()
524 .to_display_point(&display_map, Bias::Right)
525 .row() as f32
526 + 1.0;
527
528 let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
529 0.
530 } else {
531 ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
532 .floor()
533 .min(3.0)
534 };
535 if margin < 0.0 {
536 return false;
537 }
538
539 let target_top = (first_cursor_top - margin).max(0.0);
540 let target_bottom = last_cursor_bottom + margin;
541 let start_row = scroll_position.y();
542 let end_row = start_row + visible_lines;
543
544 if target_top < start_row {
545 scroll_position.set_y(target_top);
546 self.set_scroll_position(scroll_position, cx);
547 } else if target_bottom >= end_row {
548 scroll_position.set_y(target_bottom - visible_lines);
549 self.set_scroll_position(scroll_position, cx);
550 }
551
552 true
553 }
554
555 pub fn autoscroll_horizontally(
556 &mut self,
557 start_row: u32,
558 viewport_width: f32,
559 scroll_width: f32,
560 max_glyph_width: f32,
561 layouts: &[text_layout::Line],
562 cx: &mut ViewContext<Self>,
563 ) -> bool {
564 let selections = self.selections(cx);
565 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
566 let mut target_left = std::f32::INFINITY;
567 let mut target_right = 0.0_f32;
568 for selection in selections.iter() {
569 let head = selection.head().to_display_point(&display_map, Bias::Left);
570 let start_column = head.column().saturating_sub(3);
571 let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
572 target_left = target_left
573 .min(layouts[(head.row() - start_row) as usize].x_for_index(start_column as usize));
574 target_right = target_right.max(
575 layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
576 + max_glyph_width,
577 );
578 }
579 target_right = target_right.min(scroll_width);
580
581 if target_right - target_left > viewport_width {
582 return false;
583 }
584
585 let scroll_left = self.scroll_position.x() * max_glyph_width;
586 let scroll_right = scroll_left + viewport_width;
587
588 if target_left < scroll_left {
589 self.scroll_position.set_x(target_left / max_glyph_width);
590 true
591 } else if target_right > scroll_right {
592 self.scroll_position
593 .set_x((target_right - viewport_width) / max_glyph_width);
594 true
595 } else {
596 false
597 }
598 }
599
600 fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
601 match phase {
602 SelectPhase::Begin { position, add } => self.begin_selection(*position, *add, cx),
603 SelectPhase::Update {
604 position,
605 scroll_position,
606 } => self.update_selection(*position, *scroll_position, cx),
607 SelectPhase::End => self.end_selection(cx),
608 }
609 }
610
611 fn begin_selection(&mut self, position: DisplayPoint, add: bool, cx: &mut ViewContext<Self>) {
612 if !self.focused {
613 cx.focus_self();
614 cx.emit(Event::Activate);
615 }
616
617 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
618 let cursor = display_map.anchor_before(position, Bias::Left);
619 let selection = Selection {
620 id: post_inc(&mut self.next_selection_id),
621 start: cursor.clone(),
622 end: cursor,
623 reversed: false,
624 goal: SelectionGoal::None,
625 };
626
627 if !add {
628 self.update_selections(Vec::new(), false, cx);
629 }
630 self.pending_selection = Some(selection);
631
632 cx.notify();
633 }
634
635 fn update_selection(
636 &mut self,
637 position: DisplayPoint,
638 scroll_position: Vector2F,
639 cx: &mut ViewContext<Self>,
640 ) {
641 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
642 let buffer = self.buffer.read(cx);
643 let cursor = display_map.anchor_before(position, Bias::Left);
644 if let Some(selection) = self.pending_selection.as_mut() {
645 selection.set_head(buffer, cursor);
646 } else {
647 log::error!("update_selection dispatched with no pending selection");
648 return;
649 }
650
651 self.set_scroll_position(scroll_position, cx);
652 cx.notify();
653 }
654
655 fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
656 if let Some(selection) = self.pending_selection.take() {
657 let mut selections = self.selections(cx).to_vec();
658 let ix = self.selection_insertion_index(&selections, &selection.start, cx.as_ref());
659 selections.insert(ix, selection);
660 self.update_selections(selections, false, cx);
661 }
662 }
663
664 pub fn is_selecting(&self) -> bool {
665 self.pending_selection.is_some()
666 }
667
668 pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
669 if let Some(pending_selection) = self.pending_selection.take() {
670 let selections = self.selections(cx);
671 if selections.is_empty() {
672 self.update_selections(vec![pending_selection], true, cx);
673 }
674 } else {
675 let selections = self.selections(cx);
676 let mut oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
677 if selections.len() == 1 {
678 oldest_selection.start = oldest_selection.head().clone();
679 oldest_selection.end = oldest_selection.head().clone();
680 }
681 self.update_selections(vec![oldest_selection], true, cx);
682 }
683 }
684
685 fn select_ranges<I, T>(&mut self, ranges: I, autoscroll: bool, cx: &mut ViewContext<Self>)
686 where
687 I: IntoIterator<Item = Range<T>>,
688 T: ToOffset,
689 {
690 let buffer = self.buffer.read(cx);
691 let mut selections = Vec::new();
692 for range in ranges {
693 let mut start = range.start.to_offset(buffer);
694 let mut end = range.end.to_offset(buffer);
695 let reversed = if start > end {
696 mem::swap(&mut start, &mut end);
697 true
698 } else {
699 false
700 };
701 selections.push(Selection {
702 id: post_inc(&mut self.next_selection_id),
703 start: buffer.anchor_before(start),
704 end: buffer.anchor_before(end),
705 reversed,
706 goal: SelectionGoal::None,
707 });
708 }
709 self.update_selections(selections, autoscroll, cx);
710 }
711
712 #[cfg(test)]
713 fn select_display_ranges<'a, T>(
714 &mut self,
715 ranges: T,
716 cx: &mut ViewContext<Self>,
717 ) -> anyhow::Result<()>
718 where
719 T: IntoIterator<Item = &'a Range<DisplayPoint>>,
720 {
721 let mut selections = Vec::new();
722 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
723 for range in ranges {
724 let mut start = range.start;
725 let mut end = range.end;
726 let reversed = if start > end {
727 mem::swap(&mut start, &mut end);
728 true
729 } else {
730 false
731 };
732
733 selections.push(Selection {
734 id: post_inc(&mut self.next_selection_id),
735 start: display_map.anchor_before(start, Bias::Left),
736 end: display_map.anchor_before(end, Bias::Left),
737 reversed,
738 goal: SelectionGoal::None,
739 });
740 }
741 self.update_selections(selections, false, cx);
742 Ok(())
743 }
744
745 pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
746 let text = action.0.as_ref();
747 if !self.skip_autoclose_end(text, cx) {
748 self.start_transaction(cx);
749 self.insert(text, cx);
750 self.request_autoindent(cx);
751 self.autoclose_pairs(cx);
752 self.end_transaction(cx);
753 }
754 }
755
756 fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
757 self.start_transaction(cx);
758 let mut old_selections = SmallVec::<[_; 32]>::new();
759 {
760 let selections = self.selections(cx);
761 let buffer = self.buffer.read(cx);
762 for selection in selections.iter() {
763 let start = selection.start.to_offset(buffer);
764 let end = selection.end.to_offset(buffer);
765 old_selections.push((selection.id, start..end));
766 }
767 }
768
769 let mut new_selections = Vec::new();
770 self.buffer.update(cx, |buffer, cx| {
771 let edit_ranges = old_selections.iter().map(|(_, range)| range.clone());
772 buffer.edit(edit_ranges, text, cx);
773 let text_len = text.len() as isize;
774 let mut delta = 0_isize;
775 new_selections = old_selections
776 .into_iter()
777 .map(|(id, range)| {
778 let start = range.start as isize;
779 let end = range.end as isize;
780 let anchor = buffer.anchor_before((start + delta + text_len) as usize);
781 let deleted_count = end - start;
782 delta += text_len - deleted_count;
783 Selection {
784 id,
785 start: anchor.clone(),
786 end: anchor,
787 reversed: false,
788 goal: SelectionGoal::None,
789 }
790 })
791 .collect();
792 });
793
794 self.update_selections(new_selections, true, cx);
795 self.end_transaction(cx);
796 }
797
798 fn request_autoindent(&mut self, cx: &mut ViewContext<Self>) {
799 let selections = self.selections(cx);
800 let tab_size = self.build_settings.borrow()(cx).tab_size as u8;
801 self.buffer.update(cx, |buffer, _| {
802 for selection in selections.iter() {
803 let row = selection.head().to_point(&*buffer).row;
804 buffer.request_autoindent_for_line(row, tab_size, true);
805 }
806 });
807 }
808
809 fn autoclose_pairs(&mut self, cx: &mut ViewContext<Self>) {
810 let selections = self.selections(cx);
811 let new_autoclose_pair_state = self.buffer.update(cx, |buffer, cx| {
812 let autoclose_pair = buffer.language().and_then(|language| {
813 let first_selection_start = selections.first().unwrap().start.to_offset(&*buffer);
814 let pair = language.autoclose_pairs().iter().find(|pair| {
815 buffer.contains_str_at(
816 first_selection_start.saturating_sub(pair.start.len()),
817 &pair.start,
818 )
819 });
820 pair.and_then(|pair| {
821 let should_autoclose = selections[1..].iter().all(|selection| {
822 let selection_start = selection.start.to_offset(&*buffer);
823 buffer.contains_str_at(
824 selection_start.saturating_sub(pair.start.len()),
825 &pair.start,
826 )
827 });
828
829 if should_autoclose {
830 Some(pair.clone())
831 } else {
832 None
833 }
834 })
835 });
836
837 autoclose_pair.and_then(|pair| {
838 let selection_ranges = selections
839 .iter()
840 .map(|selection| {
841 let start = selection.start.to_offset(&*buffer);
842 start..start
843 })
844 .collect::<SmallVec<[_; 32]>>();
845
846 buffer.edit(selection_ranges, &pair.end, cx);
847
848 if pair.end.len() == 1 {
849 Some(AutoclosePairState {
850 ranges: selections
851 .iter()
852 .map(|selection| {
853 selection.start.bias_left(buffer)
854 ..selection.start.bias_right(buffer)
855 })
856 .collect(),
857 pair,
858 })
859 } else {
860 None
861 }
862 })
863 });
864 self.autoclose_stack.extend(new_autoclose_pair_state);
865 }
866
867 fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
868 let old_selections = self.selections(cx);
869 let autoclose_pair_state = if let Some(autoclose_pair_state) = self.autoclose_stack.last() {
870 autoclose_pair_state
871 } else {
872 return false;
873 };
874 if text != autoclose_pair_state.pair.end {
875 return false;
876 }
877
878 debug_assert_eq!(old_selections.len(), autoclose_pair_state.ranges.len());
879
880 let buffer = self.buffer.read(cx);
881 let old_selection_ranges: SmallVec<[_; 32]> = old_selections
882 .iter()
883 .map(|selection| (selection.id, selection.offset_range(buffer)))
884 .collect();
885 if old_selection_ranges
886 .iter()
887 .zip(&autoclose_pair_state.ranges)
888 .all(|((_, selection_range), autoclose_range)| {
889 let autoclose_range_end = autoclose_range.end.to_offset(buffer);
890 selection_range.is_empty() && selection_range.start == autoclose_range_end
891 })
892 {
893 let new_selections = old_selection_ranges
894 .into_iter()
895 .map(|(id, range)| {
896 let new_head = buffer.anchor_before(range.start + 1);
897 Selection {
898 id,
899 start: new_head.clone(),
900 end: new_head,
901 reversed: false,
902 goal: SelectionGoal::None,
903 }
904 })
905 .collect();
906 self.autoclose_stack.pop();
907 self.update_selections(new_selections, true, cx);
908 true
909 } else {
910 false
911 }
912 }
913
914 pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
915 self.start_transaction(cx);
916 self.select_all(&SelectAll, cx);
917 self.insert("", cx);
918 self.end_transaction(cx);
919 }
920
921 pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
922 self.start_transaction(cx);
923 let mut selections = self.selections(cx).to_vec();
924 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
925 {
926 let buffer = self.buffer.read(cx);
927 for selection in &mut selections {
928 let range = selection.point_range(buffer);
929 if range.start == range.end {
930 let head = selection.head().to_display_point(&display_map, Bias::Left);
931 let cursor = display_map
932 .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left);
933 selection.set_head(&buffer, cursor);
934 selection.goal = SelectionGoal::None;
935 }
936 }
937 }
938
939 self.update_selections(selections, true, cx);
940 self.insert("", cx);
941 self.end_transaction(cx);
942 }
943
944 pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
945 self.start_transaction(cx);
946 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
947 let mut selections = self.selections(cx).to_vec();
948 {
949 let buffer = self.buffer.read(cx);
950 for selection in &mut selections {
951 let range = selection.point_range(buffer);
952 if range.start == range.end {
953 let head = selection.head().to_display_point(&display_map, Bias::Left);
954 let cursor = display_map
955 .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right);
956 selection.set_head(&buffer, cursor);
957 selection.goal = SelectionGoal::None;
958 }
959 }
960 }
961
962 self.update_selections(selections, true, cx);
963 self.insert(&"", cx);
964 self.end_transaction(cx);
965 }
966
967 pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
968 self.start_transaction(cx);
969 let tab_size = self.build_settings.borrow()(cx).tab_size;
970 let mut selections = self.selections(cx).to_vec();
971 self.buffer.update(cx, |buffer, cx| {
972 let mut last_indented_row = None;
973 for selection in &mut selections {
974 let mut range = selection.point_range(buffer);
975 if range.is_empty() {
976 let char_column = buffer
977 .chars_for_range(Point::new(range.start.row, 0)..range.start)
978 .count();
979 let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
980 buffer.edit(
981 [range.start..range.start],
982 " ".repeat(chars_to_next_tab_stop),
983 cx,
984 );
985 range.start.column += chars_to_next_tab_stop as u32;
986
987 let head = buffer.anchor_before(range.start);
988 selection.start = head.clone();
989 selection.end = head;
990 } else {
991 for row in range.start.row..=range.end.row {
992 if last_indented_row != Some(row) {
993 let char_column = buffer.indent_column_for_line(row) as usize;
994 let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
995 let row_start = Point::new(row, 0);
996 buffer.edit(
997 [row_start..row_start],
998 " ".repeat(chars_to_next_tab_stop),
999 cx,
1000 );
1001 last_indented_row = Some(row);
1002 }
1003 }
1004 }
1005 }
1006 });
1007
1008 self.update_selections(selections, true, cx);
1009 self.end_transaction(cx);
1010 }
1011
1012 pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
1013 self.start_transaction(cx);
1014
1015 let selections = self.selections(cx);
1016 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1017 let buffer = self.buffer.read(cx);
1018
1019 let mut new_cursors = Vec::new();
1020 let mut edit_ranges = Vec::new();
1021
1022 let mut selections = selections.iter().peekable();
1023 while let Some(selection) = selections.next() {
1024 let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
1025 let goal_display_column = selection
1026 .head()
1027 .to_display_point(&display_map, Bias::Left)
1028 .column();
1029
1030 // Accumulate contiguous regions of rows that we want to delete.
1031 while let Some(next_selection) = selections.peek() {
1032 let next_rows = next_selection.spanned_rows(false, &display_map).buffer_rows;
1033 if next_rows.start <= rows.end {
1034 rows.end = next_rows.end;
1035 selections.next().unwrap();
1036 } else {
1037 break;
1038 }
1039 }
1040
1041 let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
1042 let edit_end;
1043 let cursor_buffer_row;
1044 if buffer.max_point().row >= rows.end {
1045 // If there's a line after the range, delete the \n from the end of the row range
1046 // and position the cursor on the next line.
1047 edit_end = Point::new(rows.end, 0).to_offset(buffer);
1048 cursor_buffer_row = rows.end;
1049 } else {
1050 // If there isn't a line after the range, delete the \n from the line before the
1051 // start of the row range and position the cursor there.
1052 edit_start = edit_start.saturating_sub(1);
1053 edit_end = buffer.len();
1054 cursor_buffer_row = rows.start.saturating_sub(1);
1055 }
1056
1057 let mut cursor =
1058 Point::new(cursor_buffer_row, 0).to_display_point(&display_map, Bias::Left);
1059 *cursor.column_mut() =
1060 cmp::min(goal_display_column, display_map.line_len(cursor.row()));
1061
1062 new_cursors.push((
1063 selection.id,
1064 cursor.to_buffer_point(&display_map, Bias::Left),
1065 ));
1066 edit_ranges.push(edit_start..edit_end);
1067 }
1068
1069 new_cursors.sort_unstable_by_key(|(_, range)| range.clone());
1070 let new_selections = new_cursors
1071 .into_iter()
1072 .map(|(id, cursor)| {
1073 let anchor = buffer.anchor_before(cursor);
1074 Selection {
1075 id,
1076 start: anchor.clone(),
1077 end: anchor,
1078 reversed: false,
1079 goal: SelectionGoal::None,
1080 }
1081 })
1082 .collect();
1083 self.buffer
1084 .update(cx, |buffer, cx| buffer.edit(edit_ranges, "", cx));
1085 self.update_selections(new_selections, true, cx);
1086 self.end_transaction(cx);
1087 }
1088
1089 pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
1090 self.start_transaction(cx);
1091
1092 let mut selections = self.selections(cx).to_vec();
1093 {
1094 // Temporarily bias selections right to allow newly duplicate lines to push them down
1095 // when the selections are at the beginning of a line.
1096 let buffer = self.buffer.read(cx);
1097 for selection in &mut selections {
1098 selection.start = selection.start.bias_right(buffer);
1099 selection.end = selection.end.bias_right(buffer);
1100 }
1101 }
1102 self.update_selections(selections.clone(), false, cx);
1103
1104 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1105 let buffer = self.buffer.read(cx);
1106
1107 let mut edits = Vec::new();
1108 let mut selections_iter = selections.iter_mut().peekable();
1109 while let Some(selection) = selections_iter.next() {
1110 // Avoid duplicating the same lines twice.
1111 let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
1112 while let Some(next_selection) = selections_iter.peek() {
1113 let next_rows = next_selection.spanned_rows(false, &display_map).buffer_rows;
1114 if next_rows.start <= rows.end - 1 {
1115 rows.end = next_rows.end;
1116 selections_iter.next().unwrap();
1117 } else {
1118 break;
1119 }
1120 }
1121
1122 // Copy the text from the selected row region and splice it at the start of the region.
1123 let start = Point::new(rows.start, 0);
1124 let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
1125 let text = buffer
1126 .text_for_range(start..end)
1127 .chain(Some("\n"))
1128 .collect::<String>();
1129 edits.push((start, text));
1130 }
1131
1132 self.buffer.update(cx, |buffer, cx| {
1133 for (offset, text) in edits.into_iter().rev() {
1134 buffer.edit(Some(offset..offset), text, cx);
1135 }
1136 });
1137
1138 // Restore bias on selections.
1139 let buffer = self.buffer.read(cx);
1140 for selection in &mut selections {
1141 selection.start = selection.start.bias_left(buffer);
1142 selection.end = selection.end.bias_left(buffer);
1143 }
1144 self.update_selections(selections, true, cx);
1145
1146 self.end_transaction(cx);
1147 }
1148
1149 pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
1150 self.start_transaction(cx);
1151
1152 let selections = self.selections(cx);
1153 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1154 let buffer = self.buffer.read(cx);
1155
1156 let mut edits = Vec::new();
1157 let mut new_selection_ranges = Vec::new();
1158 let mut old_folds = Vec::new();
1159 let mut new_folds = Vec::new();
1160
1161 let mut selections = selections.iter().peekable();
1162 let mut contiguous_selections = Vec::new();
1163 while let Some(selection) = selections.next() {
1164 // Accumulate contiguous regions of rows that we want to move.
1165 contiguous_selections.push(selection.point_range(buffer));
1166 let SpannedRows {
1167 mut buffer_rows,
1168 mut display_rows,
1169 } = selection.spanned_rows(false, &display_map);
1170
1171 while let Some(next_selection) = selections.peek() {
1172 let SpannedRows {
1173 buffer_rows: next_buffer_rows,
1174 display_rows: next_display_rows,
1175 } = next_selection.spanned_rows(false, &display_map);
1176 if next_buffer_rows.start <= buffer_rows.end {
1177 buffer_rows.end = next_buffer_rows.end;
1178 display_rows.end = next_display_rows.end;
1179 contiguous_selections.push(next_selection.point_range(buffer));
1180 selections.next().unwrap();
1181 } else {
1182 break;
1183 }
1184 }
1185
1186 // Cut the text from the selected rows and paste it at the start of the previous line.
1187 if display_rows.start != 0 {
1188 let start = Point::new(buffer_rows.start, 0).to_offset(buffer);
1189 let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
1190 .to_offset(buffer);
1191
1192 let prev_row_display_start = DisplayPoint::new(display_rows.start - 1, 0);
1193 let prev_row_buffer_start = display_map.prev_row_boundary(prev_row_display_start).1;
1194 let prev_row_buffer_start_offset = prev_row_buffer_start.to_offset(buffer);
1195
1196 let mut text = String::new();
1197 text.extend(buffer.text_for_range(start..end));
1198 text.push('\n');
1199 edits.push((
1200 prev_row_buffer_start_offset..prev_row_buffer_start_offset,
1201 text,
1202 ));
1203 edits.push((start - 1..end, String::new()));
1204
1205 let row_delta = buffer_rows.start - prev_row_buffer_start.row;
1206
1207 // Move selections up.
1208 for range in &mut contiguous_selections {
1209 range.start.row -= row_delta;
1210 range.end.row -= row_delta;
1211 }
1212
1213 // Move folds up.
1214 old_folds.push(start..end);
1215 for fold in display_map.folds_in_range(start..end) {
1216 let mut start = fold.start.to_point(buffer);
1217 let mut end = fold.end.to_point(buffer);
1218 start.row -= row_delta;
1219 end.row -= row_delta;
1220 new_folds.push(start..end);
1221 }
1222 }
1223
1224 new_selection_ranges.extend(contiguous_selections.drain(..));
1225 }
1226
1227 self.unfold_ranges(old_folds, cx);
1228 self.buffer.update(cx, |buffer, cx| {
1229 for (range, text) in edits.into_iter().rev() {
1230 buffer.edit(Some(range), text, cx);
1231 }
1232 });
1233 self.fold_ranges(new_folds, cx);
1234 self.select_ranges(new_selection_ranges, true, cx);
1235
1236 self.end_transaction(cx);
1237 }
1238
1239 pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
1240 self.start_transaction(cx);
1241
1242 let selections = self.selections(cx);
1243 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1244 let buffer = self.buffer.read(cx);
1245
1246 let mut edits = Vec::new();
1247 let mut new_selection_ranges = Vec::new();
1248 let mut old_folds = Vec::new();
1249 let mut new_folds = Vec::new();
1250
1251 let mut selections = selections.iter().peekable();
1252 let mut contiguous_selections = Vec::new();
1253 while let Some(selection) = selections.next() {
1254 // Accumulate contiguous regions of rows that we want to move.
1255 contiguous_selections.push(selection.point_range(buffer));
1256 let SpannedRows {
1257 mut buffer_rows,
1258 mut display_rows,
1259 } = selection.spanned_rows(false, &display_map);
1260 while let Some(next_selection) = selections.peek() {
1261 let SpannedRows {
1262 buffer_rows: next_buffer_rows,
1263 display_rows: next_display_rows,
1264 } = next_selection.spanned_rows(false, &display_map);
1265 if next_buffer_rows.start <= buffer_rows.end {
1266 buffer_rows.end = next_buffer_rows.end;
1267 display_rows.end = next_display_rows.end;
1268 contiguous_selections.push(next_selection.point_range(buffer));
1269 selections.next().unwrap();
1270 } else {
1271 break;
1272 }
1273 }
1274
1275 // Cut the text from the selected rows and paste it at the end of the next line.
1276 if display_rows.end <= display_map.max_point().row() {
1277 let start = Point::new(buffer_rows.start, 0).to_offset(buffer);
1278 let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
1279 .to_offset(buffer);
1280
1281 let next_row_display_end =
1282 DisplayPoint::new(display_rows.end, display_map.line_len(display_rows.end));
1283 let next_row_buffer_end = display_map.next_row_boundary(next_row_display_end).1;
1284 let next_row_buffer_end_offset = next_row_buffer_end.to_offset(buffer);
1285
1286 let mut text = String::new();
1287 text.push('\n');
1288 text.extend(buffer.text_for_range(start..end));
1289 edits.push((start..end + 1, String::new()));
1290 edits.push((next_row_buffer_end_offset..next_row_buffer_end_offset, text));
1291
1292 let row_delta = next_row_buffer_end.row - buffer_rows.end + 1;
1293
1294 // Move selections down.
1295 for range in &mut contiguous_selections {
1296 range.start.row += row_delta;
1297 range.end.row += row_delta;
1298 }
1299
1300 // Move folds down.
1301 old_folds.push(start..end);
1302 for fold in display_map.folds_in_range(start..end) {
1303 let mut start = fold.start.to_point(buffer);
1304 let mut end = fold.end.to_point(buffer);
1305 start.row += row_delta;
1306 end.row += row_delta;
1307 new_folds.push(start..end);
1308 }
1309 }
1310
1311 new_selection_ranges.extend(contiguous_selections.drain(..));
1312 }
1313
1314 self.unfold_ranges(old_folds, cx);
1315 self.buffer.update(cx, |buffer, cx| {
1316 for (range, text) in edits.into_iter().rev() {
1317 buffer.edit(Some(range), text, cx);
1318 }
1319 });
1320 self.fold_ranges(new_folds, cx);
1321 self.select_ranges(new_selection_ranges, true, cx);
1322
1323 self.end_transaction(cx);
1324 }
1325
1326 pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
1327 self.start_transaction(cx);
1328 let mut text = String::new();
1329 let mut selections = self.selections(cx).to_vec();
1330 let mut clipboard_selections = Vec::with_capacity(selections.len());
1331 {
1332 let buffer = self.buffer.read(cx);
1333 let max_point = buffer.max_point();
1334 for selection in &mut selections {
1335 let mut start = selection.start.to_point(buffer);
1336 let mut end = selection.end.to_point(buffer);
1337 let is_entire_line = start == end;
1338 if is_entire_line {
1339 start = Point::new(start.row, 0);
1340 end = cmp::min(max_point, Point::new(start.row + 1, 0));
1341 selection.start = buffer.anchor_before(start);
1342 selection.end = buffer.anchor_before(end);
1343 }
1344 let mut len = 0;
1345 for chunk in buffer.text_for_range(start..end) {
1346 text.push_str(chunk);
1347 len += chunk.len();
1348 }
1349 clipboard_selections.push(ClipboardSelection {
1350 len,
1351 is_entire_line,
1352 });
1353 }
1354 }
1355 self.update_selections(selections, true, cx);
1356 self.insert("", cx);
1357 self.end_transaction(cx);
1358
1359 cx.as_mut()
1360 .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1361 }
1362
1363 pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
1364 let selections = self.selections(cx);
1365 let buffer = self.buffer.read(cx);
1366 let max_point = buffer.max_point();
1367 let mut text = String::new();
1368 let mut clipboard_selections = Vec::with_capacity(selections.len());
1369 for selection in selections.iter() {
1370 let mut start = selection.start.to_point(buffer);
1371 let mut end = selection.end.to_point(buffer);
1372 let is_entire_line = start == end;
1373 if is_entire_line {
1374 start = Point::new(start.row, 0);
1375 end = cmp::min(max_point, Point::new(start.row + 1, 0));
1376 }
1377 let mut len = 0;
1378 for chunk in buffer.text_for_range(start..end) {
1379 text.push_str(chunk);
1380 len += chunk.len();
1381 }
1382 clipboard_selections.push(ClipboardSelection {
1383 len,
1384 is_entire_line,
1385 });
1386 }
1387
1388 cx.as_mut()
1389 .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1390 }
1391
1392 pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
1393 if let Some(item) = cx.as_mut().read_from_clipboard() {
1394 let clipboard_text = item.text();
1395 if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
1396 let selections = self.selections(cx);
1397 let all_selections_were_entire_line =
1398 clipboard_selections.iter().all(|s| s.is_entire_line);
1399 if clipboard_selections.len() != selections.len() {
1400 clipboard_selections.clear();
1401 }
1402
1403 let mut start_offset = 0;
1404 let mut new_selections = Vec::with_capacity(selections.len());
1405 for (i, selection) in selections.iter().enumerate() {
1406 let to_insert;
1407 let entire_line;
1408 if let Some(clipboard_selection) = clipboard_selections.get(i) {
1409 let end_offset = start_offset + clipboard_selection.len;
1410 to_insert = &clipboard_text[start_offset..end_offset];
1411 entire_line = clipboard_selection.is_entire_line;
1412 start_offset = end_offset
1413 } else {
1414 to_insert = clipboard_text.as_str();
1415 entire_line = all_selections_were_entire_line;
1416 }
1417
1418 self.buffer.update(cx, |buffer, cx| {
1419 let selection_start = selection.start.to_point(&*buffer);
1420 let selection_end = selection.end.to_point(&*buffer);
1421
1422 // If the corresponding selection was empty when this slice of the
1423 // clipboard text was written, then the entire line containing the
1424 // selection was copied. If this selection is also currently empty,
1425 // then paste the line before the current line of the buffer.
1426 let new_selection_start = selection.end.bias_right(buffer);
1427 if selection_start == selection_end && entire_line {
1428 let line_start = Point::new(selection_start.row, 0);
1429 buffer.edit(Some(line_start..line_start), to_insert, cx);
1430 } else {
1431 buffer.edit(Some(&selection.start..&selection.end), to_insert, cx);
1432 };
1433
1434 let new_selection_start = new_selection_start.bias_left(buffer);
1435 new_selections.push(Selection {
1436 id: selection.id,
1437 start: new_selection_start.clone(),
1438 end: new_selection_start,
1439 reversed: false,
1440 goal: SelectionGoal::None,
1441 });
1442 });
1443 }
1444 self.update_selections(new_selections, true, cx);
1445 } else {
1446 self.insert(clipboard_text, cx);
1447 }
1448 }
1449 }
1450
1451 pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
1452 self.buffer.update(cx, |buffer, cx| buffer.undo(cx));
1453 }
1454
1455 pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
1456 self.buffer.update(cx, |buffer, cx| buffer.redo(cx));
1457 }
1458
1459 pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
1460 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1461 let mut selections = self.selections(cx).to_vec();
1462 {
1463 for selection in &mut selections {
1464 let start = selection.start.to_display_point(&display_map, Bias::Left);
1465 let end = selection.end.to_display_point(&display_map, Bias::Left);
1466
1467 if start != end {
1468 selection.end = selection.start.clone();
1469 } else {
1470 let cursor = display_map
1471 .anchor_before(movement::left(&display_map, start).unwrap(), Bias::Left);
1472 selection.start = cursor.clone();
1473 selection.end = cursor;
1474 }
1475 selection.reversed = false;
1476 selection.goal = SelectionGoal::None;
1477 }
1478 }
1479 self.update_selections(selections, true, cx);
1480 }
1481
1482 pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
1483 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1484 let mut selections = self.selections(cx).to_vec();
1485 {
1486 let buffer = self.buffer.read(cx);
1487 for selection in &mut selections {
1488 let head = selection.head().to_display_point(&display_map, Bias::Left);
1489 let cursor = display_map
1490 .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left);
1491 selection.set_head(&buffer, cursor);
1492 selection.goal = SelectionGoal::None;
1493 }
1494 }
1495 self.update_selections(selections, true, cx);
1496 }
1497
1498 pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
1499 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1500 let mut selections = self.selections(cx).to_vec();
1501 {
1502 for selection in &mut selections {
1503 let start = selection.start.to_display_point(&display_map, Bias::Left);
1504 let end = selection.end.to_display_point(&display_map, Bias::Left);
1505
1506 if start != end {
1507 selection.start = selection.end.clone();
1508 } else {
1509 let cursor = display_map
1510 .anchor_before(movement::right(&display_map, end).unwrap(), Bias::Right);
1511 selection.start = cursor.clone();
1512 selection.end = cursor;
1513 }
1514 selection.reversed = false;
1515 selection.goal = SelectionGoal::None;
1516 }
1517 }
1518 self.update_selections(selections, true, cx);
1519 }
1520
1521 pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
1522 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1523 let mut selections = self.selections(cx).to_vec();
1524 {
1525 let app = cx.as_ref();
1526 let buffer = self.buffer.read(app);
1527 for selection in &mut selections {
1528 let head = selection.head().to_display_point(&display_map, Bias::Left);
1529 let cursor = display_map
1530 .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right);
1531 selection.set_head(&buffer, cursor);
1532 selection.goal = SelectionGoal::None;
1533 }
1534 }
1535 self.update_selections(selections, true, cx);
1536 }
1537
1538 pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
1539 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1540 if matches!(self.mode, EditorMode::SingleLine) {
1541 cx.propagate_action();
1542 } else {
1543 let mut selections = self.selections(cx).to_vec();
1544 {
1545 for selection in &mut selections {
1546 let start = selection.start.to_display_point(&display_map, Bias::Left);
1547 let end = selection.end.to_display_point(&display_map, Bias::Left);
1548 if start != end {
1549 selection.goal = SelectionGoal::None;
1550 }
1551
1552 let (start, goal) = movement::up(&display_map, start, selection.goal).unwrap();
1553 let cursor = display_map.anchor_before(start, Bias::Left);
1554 selection.start = cursor.clone();
1555 selection.end = cursor;
1556 selection.goal = goal;
1557 selection.reversed = false;
1558 }
1559 }
1560 self.update_selections(selections, true, cx);
1561 }
1562 }
1563
1564 pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
1565 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1566 let mut selections = self.selections(cx).to_vec();
1567 {
1568 let app = cx.as_ref();
1569 let buffer = self.buffer.read(app);
1570 for selection in &mut selections {
1571 let head = selection.head().to_display_point(&display_map, Bias::Left);
1572 let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap();
1573 selection.set_head(&buffer, display_map.anchor_before(head, Bias::Left));
1574 selection.goal = goal;
1575 }
1576 }
1577 self.update_selections(selections, true, cx);
1578 }
1579
1580 pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
1581 if matches!(self.mode, EditorMode::SingleLine) {
1582 cx.propagate_action();
1583 } else {
1584 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1585 let mut selections = self.selections(cx).to_vec();
1586 {
1587 for selection in &mut selections {
1588 let start = selection.start.to_display_point(&display_map, Bias::Left);
1589 let end = selection.end.to_display_point(&display_map, Bias::Left);
1590 if start != end {
1591 selection.goal = SelectionGoal::None;
1592 }
1593
1594 let (start, goal) = movement::down(&display_map, end, selection.goal).unwrap();
1595 let cursor = display_map.anchor_before(start, Bias::Right);
1596 selection.start = cursor.clone();
1597 selection.end = cursor;
1598 selection.goal = goal;
1599 selection.reversed = false;
1600 }
1601 }
1602 self.update_selections(selections, true, cx);
1603 }
1604 }
1605
1606 pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
1607 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1608 let mut selections = self.selections(cx).to_vec();
1609 {
1610 let app = cx.as_ref();
1611 let buffer = self.buffer.read(app);
1612 for selection in &mut selections {
1613 let head = selection.head().to_display_point(&display_map, Bias::Left);
1614 let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap();
1615 selection.set_head(&buffer, display_map.anchor_before(head, Bias::Right));
1616 selection.goal = goal;
1617 }
1618 }
1619 self.update_selections(selections, true, cx);
1620 }
1621
1622 pub fn move_to_previous_word_boundary(
1623 &mut self,
1624 _: &MoveToPreviousWordBoundary,
1625 cx: &mut ViewContext<Self>,
1626 ) {
1627 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1628 let mut selections = self.selections(cx).to_vec();
1629 {
1630 for selection in &mut selections {
1631 let head = selection.head().to_display_point(&display_map, Bias::Left);
1632 let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
1633 let anchor = display_map.anchor_before(new_head, Bias::Left);
1634 selection.start = anchor.clone();
1635 selection.end = anchor;
1636 selection.reversed = false;
1637 selection.goal = SelectionGoal::None;
1638 }
1639 }
1640 self.update_selections(selections, true, cx);
1641 }
1642
1643 pub fn select_to_previous_word_boundary(
1644 &mut self,
1645 _: &SelectToPreviousWordBoundary,
1646 cx: &mut ViewContext<Self>,
1647 ) {
1648 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1649 let mut selections = self.selections(cx).to_vec();
1650 {
1651 let buffer = self.buffer.read(cx);
1652 for selection in &mut selections {
1653 let head = selection.head().to_display_point(&display_map, Bias::Left);
1654 let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
1655 let anchor = display_map.anchor_before(new_head, Bias::Left);
1656 selection.set_head(buffer, anchor);
1657 selection.goal = SelectionGoal::None;
1658 }
1659 }
1660 self.update_selections(selections, true, cx);
1661 }
1662
1663 pub fn delete_to_previous_word_boundary(
1664 &mut self,
1665 _: &DeleteToPreviousWordBoundary,
1666 cx: &mut ViewContext<Self>,
1667 ) {
1668 self.start_transaction(cx);
1669 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1670 let mut selections = self.selections(cx).to_vec();
1671 {
1672 let buffer = self.buffer.read(cx);
1673 for selection in &mut selections {
1674 let range = selection.point_range(buffer);
1675 if range.start == range.end {
1676 let head = selection.head().to_display_point(&display_map, Bias::Left);
1677 let cursor = display_map.anchor_before(
1678 movement::prev_word_boundary(&display_map, head).unwrap(),
1679 Bias::Right,
1680 );
1681 selection.set_head(&buffer, cursor);
1682 selection.goal = SelectionGoal::None;
1683 }
1684 }
1685 }
1686
1687 self.update_selections(selections, true, cx);
1688 self.insert("", cx);
1689 self.end_transaction(cx);
1690 }
1691
1692 pub fn move_to_next_word_boundary(
1693 &mut self,
1694 _: &MoveToNextWordBoundary,
1695 cx: &mut ViewContext<Self>,
1696 ) {
1697 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1698 let mut selections = self.selections(cx).to_vec();
1699 {
1700 for selection in &mut selections {
1701 let head = selection.head().to_display_point(&display_map, Bias::Left);
1702 let new_head = movement::next_word_boundary(&display_map, head).unwrap();
1703 let anchor = display_map.anchor_before(new_head, Bias::Left);
1704 selection.start = anchor.clone();
1705 selection.end = anchor;
1706 selection.reversed = false;
1707 selection.goal = SelectionGoal::None;
1708 }
1709 }
1710 self.update_selections(selections, true, cx);
1711 }
1712
1713 pub fn select_to_next_word_boundary(
1714 &mut self,
1715 _: &SelectToNextWordBoundary,
1716 cx: &mut ViewContext<Self>,
1717 ) {
1718 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1719 let mut selections = self.selections(cx).to_vec();
1720 {
1721 let buffer = self.buffer.read(cx);
1722 for selection in &mut selections {
1723 let head = selection.head().to_display_point(&display_map, Bias::Left);
1724 let new_head = movement::next_word_boundary(&display_map, head).unwrap();
1725 let anchor = display_map.anchor_before(new_head, Bias::Left);
1726 selection.set_head(buffer, anchor);
1727 selection.goal = SelectionGoal::None;
1728 }
1729 }
1730 self.update_selections(selections, true, cx);
1731 }
1732
1733 pub fn delete_to_next_word_boundary(
1734 &mut self,
1735 _: &DeleteToNextWordBoundary,
1736 cx: &mut ViewContext<Self>,
1737 ) {
1738 self.start_transaction(cx);
1739 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1740 let mut selections = self.selections(cx).to_vec();
1741 {
1742 let buffer = self.buffer.read(cx);
1743 for selection in &mut selections {
1744 let range = selection.point_range(buffer);
1745 if range.start == range.end {
1746 let head = selection.head().to_display_point(&display_map, Bias::Left);
1747 let cursor = display_map.anchor_before(
1748 movement::next_word_boundary(&display_map, head).unwrap(),
1749 Bias::Right,
1750 );
1751 selection.set_head(&buffer, cursor);
1752 selection.goal = SelectionGoal::None;
1753 }
1754 }
1755 }
1756
1757 self.update_selections(selections, true, cx);
1758 self.insert("", cx);
1759 self.end_transaction(cx);
1760 }
1761
1762 pub fn move_to_beginning_of_line(
1763 &mut self,
1764 _: &MoveToBeginningOfLine,
1765 cx: &mut ViewContext<Self>,
1766 ) {
1767 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1768 let mut selections = self.selections(cx).to_vec();
1769 {
1770 for selection in &mut selections {
1771 let head = selection.head().to_display_point(&display_map, Bias::Left);
1772 let new_head = movement::line_beginning(&display_map, head, true).unwrap();
1773 let anchor = display_map.anchor_before(new_head, Bias::Left);
1774 selection.start = anchor.clone();
1775 selection.end = anchor;
1776 selection.reversed = false;
1777 selection.goal = SelectionGoal::None;
1778 }
1779 }
1780 self.update_selections(selections, true, cx);
1781 }
1782
1783 pub fn select_to_beginning_of_line(
1784 &mut self,
1785 SelectToBeginningOfLine(toggle_indent): &SelectToBeginningOfLine,
1786 cx: &mut ViewContext<Self>,
1787 ) {
1788 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1789 let mut selections = self.selections(cx).to_vec();
1790 {
1791 let buffer = self.buffer.read(cx);
1792 for selection in &mut selections {
1793 let head = selection.head().to_display_point(&display_map, Bias::Left);
1794 let new_head =
1795 movement::line_beginning(&display_map, head, *toggle_indent).unwrap();
1796 let anchor = display_map.anchor_before(new_head, Bias::Left);
1797 selection.set_head(buffer, anchor);
1798 selection.goal = SelectionGoal::None;
1799 }
1800 }
1801 self.update_selections(selections, true, cx);
1802 }
1803
1804 pub fn delete_to_beginning_of_line(
1805 &mut self,
1806 _: &DeleteToBeginningOfLine,
1807 cx: &mut ViewContext<Self>,
1808 ) {
1809 self.start_transaction(cx);
1810 self.select_to_beginning_of_line(&SelectToBeginningOfLine(false), cx);
1811 self.backspace(&Backspace, cx);
1812 self.end_transaction(cx);
1813 }
1814
1815 pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
1816 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1817 let mut selections = self.selections(cx).to_vec();
1818 {
1819 for selection in &mut selections {
1820 let head = selection.head().to_display_point(&display_map, Bias::Left);
1821 let new_head = movement::line_end(&display_map, head).unwrap();
1822 let anchor = display_map.anchor_before(new_head, Bias::Left);
1823 selection.start = anchor.clone();
1824 selection.end = anchor;
1825 selection.reversed = false;
1826 selection.goal = SelectionGoal::None;
1827 }
1828 }
1829 self.update_selections(selections, true, cx);
1830 }
1831
1832 pub fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
1833 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1834 let mut selections = self.selections(cx).to_vec();
1835 {
1836 let buffer = self.buffer.read(cx);
1837 for selection in &mut selections {
1838 let head = selection.head().to_display_point(&display_map, Bias::Left);
1839 let new_head = movement::line_end(&display_map, head).unwrap();
1840 let anchor = display_map.anchor_before(new_head, Bias::Left);
1841 selection.set_head(buffer, anchor);
1842 selection.goal = SelectionGoal::None;
1843 }
1844 }
1845 self.update_selections(selections, true, cx);
1846 }
1847
1848 pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
1849 self.start_transaction(cx);
1850 self.select_to_end_of_line(&SelectToEndOfLine, cx);
1851 self.delete(&Delete, cx);
1852 self.end_transaction(cx);
1853 }
1854
1855 pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
1856 self.start_transaction(cx);
1857 self.select_to_end_of_line(&SelectToEndOfLine, cx);
1858 self.cut(&Cut, cx);
1859 self.end_transaction(cx);
1860 }
1861
1862 pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
1863 let buffer = self.buffer.read(cx);
1864 let cursor = buffer.anchor_before(Point::new(0, 0));
1865 let selection = Selection {
1866 id: post_inc(&mut self.next_selection_id),
1867 start: cursor.clone(),
1868 end: cursor,
1869 reversed: false,
1870 goal: SelectionGoal::None,
1871 };
1872 self.update_selections(vec![selection], true, cx);
1873 }
1874
1875 pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
1876 let mut selection = self.selections(cx).last().unwrap().clone();
1877 selection.set_head(self.buffer.read(cx), Anchor::min());
1878 self.update_selections(vec![selection], true, cx);
1879 }
1880
1881 pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
1882 let buffer = self.buffer.read(cx);
1883 let cursor = buffer.anchor_before(buffer.max_point());
1884 let selection = Selection {
1885 id: post_inc(&mut self.next_selection_id),
1886 start: cursor.clone(),
1887 end: cursor,
1888 reversed: false,
1889 goal: SelectionGoal::None,
1890 };
1891 self.update_selections(vec![selection], true, cx);
1892 }
1893
1894 pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
1895 let mut selection = self.selections(cx).last().unwrap().clone();
1896 selection.set_head(self.buffer.read(cx), Anchor::max());
1897 self.update_selections(vec![selection], true, cx);
1898 }
1899
1900 pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
1901 let selection = Selection {
1902 id: post_inc(&mut self.next_selection_id),
1903 start: Anchor::min(),
1904 end: Anchor::max(),
1905 reversed: false,
1906 goal: SelectionGoal::None,
1907 };
1908 self.update_selections(vec![selection], false, cx);
1909 }
1910
1911 pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
1912 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1913 let mut selections = self.selections(cx).to_vec();
1914 let buffer = self.buffer.read(cx);
1915 let max_point = buffer.max_point();
1916 for selection in &mut selections {
1917 let rows = selection.spanned_rows(true, &display_map).buffer_rows;
1918 selection.start = buffer.anchor_before(Point::new(rows.start, 0));
1919 selection.end = buffer.anchor_before(cmp::min(max_point, Point::new(rows.end, 0)));
1920 selection.reversed = false;
1921 }
1922 self.update_selections(selections, true, cx);
1923 }
1924
1925 pub fn split_selection_into_lines(
1926 &mut self,
1927 _: &SplitSelectionIntoLines,
1928 cx: &mut ViewContext<Self>,
1929 ) {
1930 let selections = self.selections(cx);
1931 let buffer = self.buffer.read(cx);
1932
1933 let mut to_unfold = Vec::new();
1934 let mut new_selections = Vec::new();
1935 for selection in selections.iter() {
1936 let range = selection.point_range(buffer).sorted();
1937 if range.start.row != range.end.row {
1938 new_selections.push(Selection {
1939 id: post_inc(&mut self.next_selection_id),
1940 start: selection.start.clone(),
1941 end: selection.start.clone(),
1942 reversed: false,
1943 goal: SelectionGoal::None,
1944 });
1945 }
1946 for row in range.start.row + 1..range.end.row {
1947 let cursor = buffer.anchor_before(Point::new(row, buffer.line_len(row)));
1948 new_selections.push(Selection {
1949 id: post_inc(&mut self.next_selection_id),
1950 start: cursor.clone(),
1951 end: cursor,
1952 reversed: false,
1953 goal: SelectionGoal::None,
1954 });
1955 }
1956 new_selections.push(Selection {
1957 id: selection.id,
1958 start: selection.end.clone(),
1959 end: selection.end.clone(),
1960 reversed: false,
1961 goal: SelectionGoal::None,
1962 });
1963 to_unfold.push(range);
1964 }
1965 self.unfold_ranges(to_unfold, cx);
1966 self.update_selections(new_selections, true, cx);
1967 }
1968
1969 pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
1970 self.add_selection(true, cx);
1971 }
1972
1973 pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
1974 self.add_selection(false, cx);
1975 }
1976
1977 fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
1978 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1979 let mut selections = self.selections(cx).to_vec();
1980 let mut state = self.add_selections_state.take().unwrap_or_else(|| {
1981 let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
1982 let range = oldest_selection.display_range(&display_map).sorted();
1983 let columns = cmp::min(range.start.column(), range.end.column())
1984 ..cmp::max(range.start.column(), range.end.column());
1985
1986 selections.clear();
1987 let mut stack = Vec::new();
1988 for row in range.start.row()..=range.end.row() {
1989 if let Some(selection) = self.build_columnar_selection(
1990 &display_map,
1991 row,
1992 &columns,
1993 oldest_selection.reversed,
1994 ) {
1995 stack.push(selection.id);
1996 selections.push(selection);
1997 }
1998 }
1999
2000 if above {
2001 stack.reverse();
2002 }
2003
2004 AddSelectionsState { above, stack }
2005 });
2006
2007 let last_added_selection = *state.stack.last().unwrap();
2008 let mut new_selections = Vec::new();
2009 if above == state.above {
2010 let end_row = if above {
2011 0
2012 } else {
2013 display_map.max_point().row()
2014 };
2015
2016 'outer: for selection in selections {
2017 if selection.id == last_added_selection {
2018 let range = selection.display_range(&display_map).sorted();
2019 debug_assert_eq!(range.start.row(), range.end.row());
2020 let mut row = range.start.row();
2021 let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
2022 {
2023 start..end
2024 } else {
2025 cmp::min(range.start.column(), range.end.column())
2026 ..cmp::max(range.start.column(), range.end.column())
2027 };
2028
2029 while row != end_row {
2030 if above {
2031 row -= 1;
2032 } else {
2033 row += 1;
2034 }
2035
2036 if let Some(new_selection) = self.build_columnar_selection(
2037 &display_map,
2038 row,
2039 &columns,
2040 selection.reversed,
2041 ) {
2042 state.stack.push(new_selection.id);
2043 if above {
2044 new_selections.push(new_selection);
2045 new_selections.push(selection);
2046 } else {
2047 new_selections.push(selection);
2048 new_selections.push(new_selection);
2049 }
2050
2051 continue 'outer;
2052 }
2053 }
2054 }
2055
2056 new_selections.push(selection);
2057 }
2058 } else {
2059 new_selections = selections;
2060 new_selections.retain(|s| s.id != last_added_selection);
2061 state.stack.pop();
2062 }
2063
2064 self.update_selections(new_selections, true, cx);
2065 if state.stack.len() > 1 {
2066 self.add_selections_state = Some(state);
2067 }
2068 }
2069
2070 pub fn select_larger_syntax_node(
2071 &mut self,
2072 _: &SelectLargerSyntaxNode,
2073 cx: &mut ViewContext<Self>,
2074 ) {
2075 let old_selections = self.selections(cx);
2076 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2077 let buffer = self.buffer.read(cx);
2078
2079 let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2080 let mut selected_larger_node = false;
2081 let mut new_selection_ranges = Vec::new();
2082 for selection in old_selections.iter() {
2083 let old_range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2084 let mut new_range = old_range.clone();
2085 while let Some(containing_range) = buffer.range_for_syntax_ancestor(new_range.clone()) {
2086 new_range = containing_range;
2087 if !display_map.intersects_fold(new_range.start)
2088 && !display_map.intersects_fold(new_range.end)
2089 {
2090 break;
2091 }
2092 }
2093
2094 selected_larger_node |= new_range != old_range;
2095 new_selection_ranges.push((selection.id, new_range, selection.reversed));
2096 }
2097
2098 if selected_larger_node {
2099 stack.push(old_selections);
2100 new_selection_ranges.sort_unstable_by_key(|(_, range, _)| range.start.clone());
2101 let new_selections = new_selection_ranges
2102 .into_iter()
2103 .map(|(id, range, reversed)| Selection {
2104 id,
2105 start: buffer.anchor_before(range.start),
2106 end: buffer.anchor_before(range.end),
2107 reversed,
2108 goal: SelectionGoal::None,
2109 })
2110 .collect();
2111 self.update_selections(new_selections, true, cx);
2112 }
2113 self.select_larger_syntax_node_stack = stack;
2114 }
2115
2116 pub fn select_smaller_syntax_node(
2117 &mut self,
2118 _: &SelectSmallerSyntaxNode,
2119 cx: &mut ViewContext<Self>,
2120 ) {
2121 let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2122 if let Some(selections) = stack.pop() {
2123 self.update_selections(selections.to_vec(), true, cx);
2124 }
2125 self.select_larger_syntax_node_stack = stack;
2126 }
2127
2128 pub fn move_to_enclosing_bracket(
2129 &mut self,
2130 _: &MoveToEnclosingBracket,
2131 cx: &mut ViewContext<Self>,
2132 ) {
2133 let mut selections = self.selections(cx).to_vec();
2134 let buffer = self.buffer.read(cx.as_ref());
2135 for selection in &mut selections {
2136 let selection_range = selection.offset_range(buffer);
2137 if let Some((open_range, close_range)) =
2138 buffer.enclosing_bracket_ranges(selection_range.clone())
2139 {
2140 let close_range = close_range.to_inclusive();
2141 let destination = if close_range.contains(&selection_range.start)
2142 && close_range.contains(&selection_range.end)
2143 {
2144 open_range.end
2145 } else {
2146 *close_range.start()
2147 };
2148 selection.start = buffer.anchor_before(destination);
2149 selection.end = selection.start.clone();
2150 }
2151 }
2152
2153 self.update_selections(selections, true, cx);
2154 }
2155
2156 fn build_columnar_selection(
2157 &mut self,
2158 display_map: &DisplayMapSnapshot,
2159 row: u32,
2160 columns: &Range<u32>,
2161 reversed: bool,
2162 ) -> Option<Selection> {
2163 let is_empty = columns.start == columns.end;
2164 let line_len = display_map.line_len(row);
2165 if columns.start < line_len || (is_empty && columns.start == line_len) {
2166 let start = DisplayPoint::new(row, columns.start);
2167 let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
2168 Some(Selection {
2169 id: post_inc(&mut self.next_selection_id),
2170 start: display_map.anchor_before(start, Bias::Left),
2171 end: display_map.anchor_before(end, Bias::Left),
2172 reversed,
2173 goal: SelectionGoal::ColumnRange {
2174 start: columns.start,
2175 end: columns.end,
2176 },
2177 })
2178 } else {
2179 None
2180 }
2181 }
2182
2183 pub fn active_selection_sets<'a>(
2184 &'a self,
2185 cx: &'a AppContext,
2186 ) -> impl 'a + Iterator<Item = SelectionSetId> {
2187 let buffer = self.buffer.read(cx);
2188 let replica_id = buffer.replica_id();
2189 buffer
2190 .selection_sets()
2191 .filter(move |(set_id, set)| {
2192 set.active && (set_id.replica_id != replica_id || **set_id == self.selection_set_id)
2193 })
2194 .map(|(set_id, _)| *set_id)
2195 }
2196
2197 pub fn selections_in_range<'a>(
2198 &'a self,
2199 set_id: SelectionSetId,
2200 range: Range<DisplayPoint>,
2201 cx: &'a mut MutableAppContext,
2202 ) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
2203 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2204 let buffer = self.buffer.read(cx);
2205 let selections = &buffer.selection_set(set_id).unwrap().selections;
2206 let start = display_map.anchor_before(range.start, Bias::Left);
2207 let start_index = self.selection_insertion_index(selections, &start, cx);
2208 let pending_selection = if set_id.replica_id == self.buffer.read(cx).replica_id() {
2209 self.pending_selection.as_ref().and_then(|s| {
2210 let selection_range = s.display_range(&display_map);
2211 if selection_range.start <= range.end || selection_range.end <= range.end {
2212 Some(selection_range)
2213 } else {
2214 None
2215 }
2216 })
2217 } else {
2218 None
2219 };
2220 selections[start_index..]
2221 .iter()
2222 .map(move |s| s.display_range(&display_map))
2223 .take_while(move |r| r.start <= range.end || r.end <= range.end)
2224 .chain(pending_selection)
2225 }
2226
2227 fn selection_insertion_index(
2228 &self,
2229 selections: &[Selection],
2230 start: &Anchor,
2231 cx: &AppContext,
2232 ) -> usize {
2233 let buffer = self.buffer.read(cx);
2234 match selections.binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap()) {
2235 Ok(index) => index,
2236 Err(index) => {
2237 if index > 0
2238 && selections[index - 1].end.cmp(&start, buffer).unwrap() == Ordering::Greater
2239 {
2240 index - 1
2241 } else {
2242 index
2243 }
2244 }
2245 }
2246 }
2247
2248 fn selections(&mut self, cx: &mut ViewContext<Self>) -> Arc<[Selection]> {
2249 self.end_selection(cx);
2250 let buffer = self.buffer.read(cx);
2251 buffer
2252 .selection_set(self.selection_set_id)
2253 .unwrap()
2254 .selections
2255 .clone()
2256 }
2257
2258 fn update_selections(
2259 &mut self,
2260 mut selections: Vec<Selection>,
2261 autoscroll: bool,
2262 cx: &mut ViewContext<Self>,
2263 ) {
2264 // Merge overlapping selections.
2265 let buffer = self.buffer.read(cx);
2266 let mut i = 1;
2267 while i < selections.len() {
2268 if selections[i - 1]
2269 .end
2270 .cmp(&selections[i].start, buffer)
2271 .unwrap()
2272 >= Ordering::Equal
2273 {
2274 let removed = selections.remove(i);
2275 if removed.start.cmp(&selections[i - 1].start, buffer).unwrap() < Ordering::Equal {
2276 selections[i - 1].start = removed.start;
2277 }
2278 if removed.end.cmp(&selections[i - 1].end, buffer).unwrap() > Ordering::Equal {
2279 selections[i - 1].end = removed.end;
2280 }
2281 } else {
2282 i += 1;
2283 }
2284 }
2285
2286 self.add_selections_state = None;
2287 self.select_larger_syntax_node_stack.clear();
2288 while let Some(autoclose_pair_state) = self.autoclose_stack.last() {
2289 let all_selections_inside_autoclose_ranges =
2290 if selections.len() == autoclose_pair_state.ranges.len() {
2291 selections.iter().zip(&autoclose_pair_state.ranges).all(
2292 |(selection, autoclose_range)| {
2293 let head = selection.head();
2294 autoclose_range.start.cmp(head, buffer).unwrap() <= Ordering::Equal
2295 && autoclose_range.end.cmp(head, buffer).unwrap() >= Ordering::Equal
2296 },
2297 )
2298 } else {
2299 false
2300 };
2301
2302 if all_selections_inside_autoclose_ranges {
2303 break;
2304 } else {
2305 self.autoclose_stack.pop();
2306 }
2307 }
2308
2309 if autoscroll {
2310 self.autoscroll_requested = true;
2311 cx.notify();
2312 }
2313
2314 self.pause_cursor_blinking(cx);
2315
2316 self.buffer.update(cx, |buffer, cx| {
2317 buffer
2318 .update_selection_set(self.selection_set_id, selections, cx)
2319 .unwrap();
2320 });
2321 }
2322
2323 fn start_transaction(&self, cx: &mut ViewContext<Self>) {
2324 self.buffer.update(cx, |buffer, _| {
2325 buffer
2326 .start_transaction(Some(self.selection_set_id))
2327 .unwrap()
2328 });
2329 }
2330
2331 fn end_transaction(&self, cx: &mut ViewContext<Self>) {
2332 self.buffer.update(cx, |buffer, cx| {
2333 buffer
2334 .end_transaction(Some(self.selection_set_id), cx)
2335 .unwrap()
2336 });
2337 }
2338
2339 pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
2340 log::info!("Editor::page_up");
2341 }
2342
2343 pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
2344 log::info!("Editor::page_down");
2345 }
2346
2347 pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
2348 let mut fold_ranges = Vec::new();
2349
2350 let selections = self.selections(cx);
2351 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2352 for selection in selections.iter() {
2353 let range = selection.display_range(&display_map).sorted();
2354 let buffer_start_row = range.start.to_buffer_point(&display_map, Bias::Left).row;
2355
2356 for row in (0..=range.end.row()).rev() {
2357 if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
2358 let fold_range = self.foldable_range_for_line(&display_map, row);
2359 if fold_range.end.row >= buffer_start_row {
2360 fold_ranges.push(fold_range);
2361 if row <= range.start.row() {
2362 break;
2363 }
2364 }
2365 }
2366 }
2367 }
2368
2369 self.fold_ranges(fold_ranges, cx);
2370 }
2371
2372 pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
2373 let selections = self.selections(cx);
2374 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2375 let buffer = self.buffer.read(cx);
2376 let ranges = selections
2377 .iter()
2378 .map(|s| {
2379 let range = s.display_range(&display_map).sorted();
2380 let mut start = range.start.to_buffer_point(&display_map, Bias::Left);
2381 let mut end = range.end.to_buffer_point(&display_map, Bias::Left);
2382 start.column = 0;
2383 end.column = buffer.line_len(end.row);
2384 start..end
2385 })
2386 .collect::<Vec<_>>();
2387 self.unfold_ranges(ranges, cx);
2388 }
2389
2390 fn is_line_foldable(&self, display_map: &DisplayMapSnapshot, display_row: u32) -> bool {
2391 let max_point = display_map.max_point();
2392 if display_row >= max_point.row() {
2393 false
2394 } else {
2395 let (start_indent, is_blank) = display_map.line_indent(display_row);
2396 if is_blank {
2397 false
2398 } else {
2399 for display_row in display_row + 1..=max_point.row() {
2400 let (indent, is_blank) = display_map.line_indent(display_row);
2401 if !is_blank {
2402 return indent > start_indent;
2403 }
2404 }
2405 false
2406 }
2407 }
2408 }
2409
2410 fn foldable_range_for_line(
2411 &self,
2412 display_map: &DisplayMapSnapshot,
2413 start_row: u32,
2414 ) -> Range<Point> {
2415 let max_point = display_map.max_point();
2416
2417 let (start_indent, _) = display_map.line_indent(start_row);
2418 let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
2419 let mut end = None;
2420 for row in start_row + 1..=max_point.row() {
2421 let (indent, is_blank) = display_map.line_indent(row);
2422 if !is_blank && indent <= start_indent {
2423 end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
2424 break;
2425 }
2426 }
2427
2428 let end = end.unwrap_or(max_point);
2429 return start.to_buffer_point(display_map, Bias::Left)
2430 ..end.to_buffer_point(display_map, Bias::Left);
2431 }
2432
2433 pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
2434 let selections = self.selections(cx);
2435 let buffer = self.buffer.read(cx);
2436 let ranges = selections
2437 .iter()
2438 .map(|s| s.point_range(buffer).sorted())
2439 .collect();
2440 self.fold_ranges(ranges, cx);
2441 }
2442
2443 fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
2444 if !ranges.is_empty() {
2445 self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
2446 self.autoscroll_requested = true;
2447 cx.notify();
2448 }
2449 }
2450
2451 fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
2452 if !ranges.is_empty() {
2453 self.display_map
2454 .update(cx, |map, cx| map.unfold(ranges, cx));
2455 self.autoscroll_requested = true;
2456 cx.notify();
2457 }
2458 }
2459
2460 pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
2461 self.display_map
2462 .update(cx, |map, cx| map.snapshot(cx))
2463 .longest_row()
2464 }
2465
2466 pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
2467 self.display_map
2468 .update(cx, |map, cx| map.snapshot(cx))
2469 .max_point()
2470 }
2471
2472 pub fn text(&self, cx: &AppContext) -> String {
2473 self.buffer.read(cx).text()
2474 }
2475
2476 pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
2477 self.display_map
2478 .update(cx, |map, cx| map.snapshot(cx))
2479 .text()
2480 }
2481
2482 // pub fn font_size(&self) -> f32 {
2483 // self.settings.font_size
2484 // }
2485
2486 pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool {
2487 self.display_map
2488 .update(cx, |map, cx| map.set_wrap_width(Some(width), cx))
2489 }
2490
2491 fn next_blink_epoch(&mut self) -> usize {
2492 self.blink_epoch += 1;
2493 self.blink_epoch
2494 }
2495
2496 fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
2497 self.show_local_cursors = true;
2498 cx.notify();
2499
2500 let epoch = self.next_blink_epoch();
2501 cx.spawn(|this, mut cx| {
2502 let this = this.downgrade();
2503 async move {
2504 Timer::after(CURSOR_BLINK_INTERVAL).await;
2505 if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
2506 this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
2507 }
2508 }
2509 })
2510 .detach();
2511 }
2512
2513 fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
2514 if epoch == self.blink_epoch {
2515 self.blinking_paused = false;
2516 self.blink_cursors(epoch, cx);
2517 }
2518 }
2519
2520 fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
2521 if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
2522 self.show_local_cursors = !self.show_local_cursors;
2523 cx.notify();
2524
2525 let epoch = self.next_blink_epoch();
2526 cx.spawn(|this, mut cx| {
2527 let this = this.downgrade();
2528 async move {
2529 Timer::after(CURSOR_BLINK_INTERVAL).await;
2530 if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
2531 this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
2532 }
2533 }
2534 })
2535 .detach();
2536 }
2537 }
2538
2539 pub fn show_local_cursors(&self) -> bool {
2540 self.show_local_cursors
2541 }
2542
2543 fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, cx: &mut ViewContext<Self>) {
2544 cx.notify();
2545 }
2546
2547 fn on_buffer_event(
2548 &mut self,
2549 _: ModelHandle<Buffer>,
2550 event: &buffer::Event,
2551 cx: &mut ViewContext<Self>,
2552 ) {
2553 match event {
2554 buffer::Event::Edited => cx.emit(Event::Edited),
2555 buffer::Event::Dirtied => cx.emit(Event::Dirtied),
2556 buffer::Event::Saved => cx.emit(Event::Saved),
2557 buffer::Event::FileHandleChanged => cx.emit(Event::FileHandleChanged),
2558 buffer::Event::Reloaded => cx.emit(Event::FileHandleChanged),
2559 buffer::Event::Closed => cx.emit(Event::Closed),
2560 buffer::Event::Reparsed => {}
2561 }
2562 }
2563
2564 fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
2565 cx.notify();
2566 }
2567}
2568
2569impl Snapshot {
2570 pub fn is_empty(&self) -> bool {
2571 self.display_snapshot.is_empty()
2572 }
2573
2574 pub fn is_focused(&self) -> bool {
2575 self.is_focused
2576 }
2577
2578 pub fn placeholder_text(&self) -> Option<&Arc<str>> {
2579 self.placeholder_text.as_ref()
2580 }
2581
2582 pub fn buffer_row_count(&self) -> u32 {
2583 self.display_snapshot.buffer_row_count()
2584 }
2585
2586 pub fn buffer_rows(&self, start_row: u32) -> BufferRows {
2587 self.display_snapshot.buffer_rows(start_row)
2588 }
2589
2590 pub fn highlighted_chunks_for_rows(
2591 &mut self,
2592 display_rows: Range<u32>,
2593 ) -> display_map::HighlightedChunks {
2594 self.display_snapshot
2595 .highlighted_chunks_for_rows(display_rows)
2596 }
2597
2598 pub fn scroll_position(&self) -> Vector2F {
2599 compute_scroll_position(
2600 &self.display_snapshot,
2601 self.scroll_position,
2602 &self.scroll_top_anchor,
2603 )
2604 }
2605
2606 pub fn max_point(&self) -> DisplayPoint {
2607 self.display_snapshot.max_point()
2608 }
2609
2610 pub fn longest_row(&self) -> u32 {
2611 self.display_snapshot.longest_row()
2612 }
2613
2614 pub fn line_len(&self, display_row: u32) -> u32 {
2615 self.display_snapshot.line_len(display_row)
2616 }
2617
2618 pub fn line(&self, display_row: u32) -> String {
2619 self.display_snapshot.line(display_row)
2620 }
2621
2622 pub fn prev_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
2623 self.display_snapshot.prev_row_boundary(point)
2624 }
2625
2626 pub fn next_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
2627 self.display_snapshot.next_row_boundary(point)
2628 }
2629}
2630
2631impl EditorSettings {
2632 #[cfg(any(test, feature = "test-support"))]
2633 pub fn test(cx: &AppContext) -> Self {
2634 Self {
2635 tab_size: 4,
2636 style: {
2637 let font_cache: &gpui::FontCache = cx.font_cache();
2638 let font_family_name = Arc::from("Monaco");
2639 let font_properties = Default::default();
2640 let font_family_id = font_cache.load_family(&[&font_family_name]).unwrap();
2641 let font_id = font_cache
2642 .select_font(font_family_id, &font_properties)
2643 .unwrap();
2644 EditorStyle {
2645 text: TextStyle {
2646 font_family_name,
2647 font_family_id,
2648 font_id,
2649 font_size: 14.,
2650 color: Color::from_u32(0xff0000ff),
2651 font_properties,
2652 underline: false,
2653 },
2654 placeholder_text: None,
2655 background: Default::default(),
2656 gutter_background: Default::default(),
2657 active_line_background: Default::default(),
2658 line_number: Default::default(),
2659 line_number_active: Default::default(),
2660 selection: Default::default(),
2661 guest_selections: Default::default(),
2662 syntax: Default::default(),
2663 }
2664 },
2665 }
2666 }
2667}
2668
2669fn compute_scroll_position(
2670 snapshot: &DisplayMapSnapshot,
2671 mut scroll_position: Vector2F,
2672 scroll_top_anchor: &Anchor,
2673) -> Vector2F {
2674 let scroll_top = scroll_top_anchor
2675 .to_display_point(snapshot, Bias::Left)
2676 .row() as f32;
2677 scroll_position.set_y(scroll_top + scroll_position.y());
2678 scroll_position
2679}
2680
2681pub enum Event {
2682 Activate,
2683 Edited,
2684 Blurred,
2685 Dirtied,
2686 Saved,
2687 FileHandleChanged,
2688 Closed,
2689}
2690
2691impl Entity for Editor {
2692 type Event = Event;
2693
2694 fn release(&mut self, cx: &mut MutableAppContext) {
2695 self.buffer.update(cx, |buffer, cx| {
2696 buffer
2697 .remove_selection_set(self.selection_set_id, cx)
2698 .unwrap();
2699 });
2700 }
2701}
2702
2703impl View for Editor {
2704 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
2705 let settings = self.build_settings.borrow_mut()(cx);
2706 self.display_map.update(cx, |map, cx| {
2707 map.set_font(
2708 settings.style.text.font_id,
2709 settings.style.text.font_size,
2710 cx,
2711 )
2712 });
2713 EditorElement::new(self.handle.clone(), settings).boxed()
2714 }
2715
2716 fn ui_name() -> &'static str {
2717 "Editor"
2718 }
2719
2720 fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
2721 self.focused = true;
2722 self.blink_cursors(self.blink_epoch, cx);
2723 self.buffer.update(cx, |buffer, cx| {
2724 buffer
2725 .set_active_selection_set(Some(self.selection_set_id), cx)
2726 .unwrap();
2727 });
2728 }
2729
2730 fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
2731 self.focused = false;
2732 self.show_local_cursors = false;
2733 self.buffer.update(cx, |buffer, cx| {
2734 buffer.set_active_selection_set(None, cx).unwrap();
2735 });
2736 cx.emit(Event::Blurred);
2737 cx.notify();
2738 }
2739
2740 fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
2741 let mut cx = Self::default_keymap_context();
2742 let mode = match self.mode {
2743 EditorMode::SingleLine => "single_line",
2744 EditorMode::AutoHeight { .. } => "auto_height",
2745 EditorMode::Full => "full",
2746 };
2747 cx.map.insert("mode".into(), mode.into());
2748 cx
2749 }
2750}
2751
2752impl SelectionExt for Selection {
2753 fn display_range(&self, map: &DisplayMapSnapshot) -> Range<DisplayPoint> {
2754 let start = self.start.to_display_point(map, Bias::Left);
2755 let end = self.end.to_display_point(map, Bias::Left);
2756 if self.reversed {
2757 end..start
2758 } else {
2759 start..end
2760 }
2761 }
2762
2763 fn spanned_rows(
2764 &self,
2765 include_end_if_at_line_start: bool,
2766 map: &DisplayMapSnapshot,
2767 ) -> SpannedRows {
2768 let display_start = self.start.to_display_point(map, Bias::Left);
2769 let mut display_end = self.end.to_display_point(map, Bias::Right);
2770 if !include_end_if_at_line_start
2771 && display_end.row() != map.max_point().row()
2772 && display_start.row() != display_end.row()
2773 && display_end.column() == 0
2774 {
2775 *display_end.row_mut() -= 1;
2776 }
2777
2778 let (display_start, buffer_start) = map.prev_row_boundary(display_start);
2779 let (display_end, buffer_end) = map.next_row_boundary(display_end);
2780
2781 SpannedRows {
2782 buffer_rows: buffer_start.row..buffer_end.row + 1,
2783 display_rows: display_start.row()..display_end.row() + 1,
2784 }
2785 }
2786}
2787
2788#[cfg(test)]
2789mod tests {
2790 use super::*;
2791 use crate::test::sample_text;
2792 use buffer::{History, Point};
2793 use unindent::Unindent;
2794
2795 #[gpui::test]
2796 fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
2797 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
2798 let settings = EditorSettings::test(cx);
2799 let (_, editor) =
2800 cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
2801
2802 editor.update(cx, |view, cx| {
2803 view.begin_selection(DisplayPoint::new(2, 2), false, cx);
2804 });
2805
2806 assert_eq!(
2807 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2808 [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
2809 );
2810
2811 editor.update(cx, |view, cx| {
2812 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
2813 });
2814
2815 assert_eq!(
2816 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2817 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2818 );
2819
2820 editor.update(cx, |view, cx| {
2821 view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
2822 });
2823
2824 assert_eq!(
2825 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2826 [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
2827 );
2828
2829 editor.update(cx, |view, cx| {
2830 view.end_selection(cx);
2831 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
2832 });
2833
2834 assert_eq!(
2835 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2836 [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
2837 );
2838
2839 editor.update(cx, |view, cx| {
2840 view.begin_selection(DisplayPoint::new(3, 3), true, cx);
2841 view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), cx);
2842 });
2843
2844 assert_eq!(
2845 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2846 [
2847 DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
2848 DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
2849 ]
2850 );
2851
2852 editor.update(cx, |view, cx| {
2853 view.end_selection(cx);
2854 });
2855
2856 assert_eq!(
2857 editor.update(cx, |view, cx| view.selection_ranges(cx)),
2858 [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
2859 );
2860 }
2861
2862 #[gpui::test]
2863 fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
2864 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
2865 let settings = EditorSettings::test(cx);
2866 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
2867
2868 view.update(cx, |view, cx| {
2869 view.begin_selection(DisplayPoint::new(2, 2), false, cx);
2870 assert_eq!(
2871 view.selection_ranges(cx),
2872 [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
2873 );
2874 });
2875
2876 view.update(cx, |view, cx| {
2877 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
2878 assert_eq!(
2879 view.selection_ranges(cx),
2880 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2881 );
2882 });
2883
2884 view.update(cx, |view, cx| {
2885 view.cancel(&Cancel, cx);
2886 view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
2887 assert_eq!(
2888 view.selection_ranges(cx),
2889 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2890 );
2891 });
2892 }
2893
2894 #[gpui::test]
2895 fn test_cancel(cx: &mut gpui::MutableAppContext) {
2896 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
2897 let settings = EditorSettings::test(cx);
2898 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
2899
2900 view.update(cx, |view, cx| {
2901 view.begin_selection(DisplayPoint::new(3, 4), false, cx);
2902 view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
2903 view.end_selection(cx);
2904
2905 view.begin_selection(DisplayPoint::new(0, 1), true, cx);
2906 view.update_selection(DisplayPoint::new(0, 3), Vector2F::zero(), cx);
2907 view.end_selection(cx);
2908 assert_eq!(
2909 view.selection_ranges(cx),
2910 [
2911 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
2912 DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
2913 ]
2914 );
2915 });
2916
2917 view.update(cx, |view, cx| {
2918 view.cancel(&Cancel, cx);
2919 assert_eq!(
2920 view.selection_ranges(cx),
2921 [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
2922 );
2923 });
2924
2925 view.update(cx, |view, cx| {
2926 view.cancel(&Cancel, cx);
2927 assert_eq!(
2928 view.selection_ranges(cx),
2929 [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
2930 );
2931 });
2932 }
2933
2934 #[gpui::test]
2935 fn test_fold(cx: &mut gpui::MutableAppContext) {
2936 let buffer = cx.add_model(|cx| {
2937 Buffer::new(
2938 0,
2939 "
2940 impl Foo {
2941 // Hello!
2942
2943 fn a() {
2944 1
2945 }
2946
2947 fn b() {
2948 2
2949 }
2950
2951 fn c() {
2952 3
2953 }
2954 }
2955 "
2956 .unindent(),
2957 cx,
2958 )
2959 });
2960 let settings = EditorSettings::test(&cx);
2961 let (_, view) = cx.add_window(Default::default(), |cx| {
2962 build_editor(buffer.clone(), settings, cx)
2963 });
2964
2965 view.update(cx, |view, cx| {
2966 view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx)
2967 .unwrap();
2968 view.fold(&Fold, cx);
2969 assert_eq!(
2970 view.display_text(cx),
2971 "
2972 impl Foo {
2973 // Hello!
2974
2975 fn a() {
2976 1
2977 }
2978
2979 fn b() {…
2980 }
2981
2982 fn c() {…
2983 }
2984 }
2985 "
2986 .unindent(),
2987 );
2988
2989 view.fold(&Fold, cx);
2990 assert_eq!(
2991 view.display_text(cx),
2992 "
2993 impl Foo {…
2994 }
2995 "
2996 .unindent(),
2997 );
2998
2999 view.unfold(&Unfold, cx);
3000 assert_eq!(
3001 view.display_text(cx),
3002 "
3003 impl Foo {
3004 // Hello!
3005
3006 fn a() {
3007 1
3008 }
3009
3010 fn b() {…
3011 }
3012
3013 fn c() {…
3014 }
3015 }
3016 "
3017 .unindent(),
3018 );
3019
3020 view.unfold(&Unfold, cx);
3021 assert_eq!(view.display_text(cx), buffer.read(cx).text());
3022 });
3023 }
3024
3025 #[gpui::test]
3026 fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
3027 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6), cx));
3028 let settings = EditorSettings::test(&cx);
3029 let (_, view) = cx.add_window(Default::default(), |cx| {
3030 build_editor(buffer.clone(), settings, cx)
3031 });
3032
3033 buffer.update(cx, |buffer, cx| {
3034 buffer.edit(
3035 vec![
3036 Point::new(1, 0)..Point::new(1, 0),
3037 Point::new(1, 1)..Point::new(1, 1),
3038 ],
3039 "\t",
3040 cx,
3041 );
3042 });
3043
3044 view.update(cx, |view, cx| {
3045 assert_eq!(
3046 view.selection_ranges(cx),
3047 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3048 );
3049
3050 view.move_down(&MoveDown, cx);
3051 assert_eq!(
3052 view.selection_ranges(cx),
3053 &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3054 );
3055
3056 view.move_right(&MoveRight, cx);
3057 assert_eq!(
3058 view.selection_ranges(cx),
3059 &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
3060 );
3061
3062 view.move_left(&MoveLeft, cx);
3063 assert_eq!(
3064 view.selection_ranges(cx),
3065 &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3066 );
3067
3068 view.move_up(&MoveUp, cx);
3069 assert_eq!(
3070 view.selection_ranges(cx),
3071 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3072 );
3073
3074 view.move_to_end(&MoveToEnd, cx);
3075 assert_eq!(
3076 view.selection_ranges(cx),
3077 &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
3078 );
3079
3080 view.move_to_beginning(&MoveToBeginning, cx);
3081 assert_eq!(
3082 view.selection_ranges(cx),
3083 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3084 );
3085
3086 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx)
3087 .unwrap();
3088 view.select_to_beginning(&SelectToBeginning, cx);
3089 assert_eq!(
3090 view.selection_ranges(cx),
3091 &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
3092 );
3093
3094 view.select_to_end(&SelectToEnd, cx);
3095 assert_eq!(
3096 view.selection_ranges(cx),
3097 &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
3098 );
3099 });
3100 }
3101
3102 #[gpui::test]
3103 fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
3104 let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx));
3105 let settings = EditorSettings::test(&cx);
3106 let (_, view) = cx.add_window(Default::default(), |cx| {
3107 build_editor(buffer.clone(), settings, cx)
3108 });
3109
3110 assert_eq!('ⓐ'.len_utf8(), 3);
3111 assert_eq!('α'.len_utf8(), 2);
3112
3113 view.update(cx, |view, cx| {
3114 view.fold_ranges(
3115 vec![
3116 Point::new(0, 6)..Point::new(0, 12),
3117 Point::new(1, 2)..Point::new(1, 4),
3118 Point::new(2, 4)..Point::new(2, 8),
3119 ],
3120 cx,
3121 );
3122 assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
3123
3124 view.move_right(&MoveRight, cx);
3125 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐ".len())]);
3126 view.move_right(&MoveRight, cx);
3127 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
3128 view.move_right(&MoveRight, cx);
3129 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
3130
3131 view.move_down(&MoveDown, cx);
3132 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…".len())]);
3133 view.move_left(&MoveLeft, cx);
3134 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab".len())]);
3135 view.move_left(&MoveLeft, cx);
3136 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "a".len())]);
3137
3138 view.move_down(&MoveDown, cx);
3139 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "α".len())]);
3140 view.move_right(&MoveRight, cx);
3141 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ".len())]);
3142 view.move_right(&MoveRight, cx);
3143 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…".len())]);
3144 view.move_right(&MoveRight, cx);
3145 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…ε".len())]);
3146
3147 view.move_up(&MoveUp, cx);
3148 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…e".len())]);
3149 view.move_up(&MoveUp, cx);
3150 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…ⓔ".len())]);
3151 view.move_left(&MoveLeft, cx);
3152 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
3153 view.move_left(&MoveLeft, cx);
3154 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
3155 view.move_left(&MoveLeft, cx);
3156 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐ".len())]);
3157 });
3158 }
3159
3160 #[gpui::test]
3161 fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
3162 let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx));
3163 let settings = EditorSettings::test(&cx);
3164 let (_, view) = cx.add_window(Default::default(), |cx| {
3165 build_editor(buffer.clone(), settings, cx)
3166 });
3167 view.update(cx, |view, cx| {
3168 view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx)
3169 .unwrap();
3170
3171 view.move_down(&MoveDown, cx);
3172 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "abcd".len())]);
3173
3174 view.move_down(&MoveDown, cx);
3175 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
3176
3177 view.move_down(&MoveDown, cx);
3178 assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
3179
3180 view.move_down(&MoveDown, cx);
3181 assert_eq!(view.selection_ranges(cx), &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]);
3182
3183 view.move_up(&MoveUp, cx);
3184 assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
3185
3186 view.move_up(&MoveUp, cx);
3187 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
3188 });
3189 }
3190
3191 #[gpui::test]
3192 fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
3193 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\n def", cx));
3194 let settings = EditorSettings::test(&cx);
3195 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3196 view.update(cx, |view, cx| {
3197 view.select_display_ranges(
3198 &[
3199 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3200 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
3201 ],
3202 cx,
3203 )
3204 .unwrap();
3205 });
3206
3207 view.update(cx, |view, cx| {
3208 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3209 assert_eq!(
3210 view.selection_ranges(cx),
3211 &[
3212 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3213 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3214 ]
3215 );
3216 });
3217
3218 view.update(cx, |view, cx| {
3219 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3220 assert_eq!(
3221 view.selection_ranges(cx),
3222 &[
3223 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3224 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3225 ]
3226 );
3227 });
3228
3229 view.update(cx, |view, cx| {
3230 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3231 assert_eq!(
3232 view.selection_ranges(cx),
3233 &[
3234 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3235 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3236 ]
3237 );
3238 });
3239
3240 view.update(cx, |view, cx| {
3241 view.move_to_end_of_line(&MoveToEndOfLine, cx);
3242 assert_eq!(
3243 view.selection_ranges(cx),
3244 &[
3245 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3246 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3247 ]
3248 );
3249 });
3250
3251 // Moving to the end of line again is a no-op.
3252 view.update(cx, |view, cx| {
3253 view.move_to_end_of_line(&MoveToEndOfLine, cx);
3254 assert_eq!(
3255 view.selection_ranges(cx),
3256 &[
3257 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3258 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3259 ]
3260 );
3261 });
3262
3263 view.update(cx, |view, cx| {
3264 view.move_left(&MoveLeft, cx);
3265 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3266 assert_eq!(
3267 view.selection_ranges(cx),
3268 &[
3269 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3270 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
3271 ]
3272 );
3273 });
3274
3275 view.update(cx, |view, cx| {
3276 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3277 assert_eq!(
3278 view.selection_ranges(cx),
3279 &[
3280 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3281 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
3282 ]
3283 );
3284 });
3285
3286 view.update(cx, |view, cx| {
3287 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3288 assert_eq!(
3289 view.selection_ranges(cx),
3290 &[
3291 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3292 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
3293 ]
3294 );
3295 });
3296
3297 view.update(cx, |view, cx| {
3298 view.select_to_end_of_line(&SelectToEndOfLine, cx);
3299 assert_eq!(
3300 view.selection_ranges(cx),
3301 &[
3302 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
3303 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
3304 ]
3305 );
3306 });
3307
3308 view.update(cx, |view, cx| {
3309 view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
3310 assert_eq!(view.display_text(cx), "ab\n de");
3311 assert_eq!(
3312 view.selection_ranges(cx),
3313 &[
3314 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3315 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
3316 ]
3317 );
3318 });
3319
3320 view.update(cx, |view, cx| {
3321 view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
3322 assert_eq!(view.display_text(cx), "\n");
3323 assert_eq!(
3324 view.selection_ranges(cx),
3325 &[
3326 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3327 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3328 ]
3329 );
3330 });
3331 }
3332
3333 #[gpui::test]
3334 fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
3335 let buffer =
3336 cx.add_model(|cx| Buffer::new(0, "use std::str::{foo, bar}\n\n {baz.qux()}", cx));
3337 let settings = EditorSettings::test(&cx);
3338 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3339 view.update(cx, |view, cx| {
3340 view.select_display_ranges(
3341 &[
3342 DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
3343 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
3344 ],
3345 cx,
3346 )
3347 .unwrap();
3348 });
3349
3350 view.update(cx, |view, cx| {
3351 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3352 assert_eq!(
3353 view.selection_ranges(cx),
3354 &[
3355 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3356 DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3357 ]
3358 );
3359 });
3360
3361 view.update(cx, |view, cx| {
3362 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3363 assert_eq!(
3364 view.selection_ranges(cx),
3365 &[
3366 DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3367 DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
3368 ]
3369 );
3370 });
3371
3372 view.update(cx, |view, cx| {
3373 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3374 assert_eq!(
3375 view.selection_ranges(cx),
3376 &[
3377 DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
3378 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
3379 ]
3380 );
3381 });
3382
3383 view.update(cx, |view, cx| {
3384 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3385 assert_eq!(
3386 view.selection_ranges(cx),
3387 &[
3388 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3389 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3390 ]
3391 );
3392 });
3393
3394 view.update(cx, |view, cx| {
3395 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3396 assert_eq!(
3397 view.selection_ranges(cx),
3398 &[
3399 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3400 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 23),
3401 ]
3402 );
3403 });
3404
3405 view.update(cx, |view, cx| {
3406 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3407 assert_eq!(
3408 view.selection_ranges(cx),
3409 &[
3410 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3411 DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
3412 ]
3413 );
3414 });
3415
3416 view.update(cx, |view, cx| {
3417 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3418 assert_eq!(
3419 view.selection_ranges(cx),
3420 &[
3421 DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3422 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3423 ]
3424 );
3425 });
3426
3427 view.update(cx, |view, cx| {
3428 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3429 assert_eq!(
3430 view.selection_ranges(cx),
3431 &[
3432 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3433 DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3434 ]
3435 );
3436 });
3437
3438 view.update(cx, |view, cx| {
3439 view.move_right(&MoveRight, cx);
3440 view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
3441 assert_eq!(
3442 view.selection_ranges(cx),
3443 &[
3444 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3445 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
3446 ]
3447 );
3448 });
3449
3450 view.update(cx, |view, cx| {
3451 view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
3452 assert_eq!(
3453 view.selection_ranges(cx),
3454 &[
3455 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 7),
3456 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 2),
3457 ]
3458 );
3459 });
3460
3461 view.update(cx, |view, cx| {
3462 view.select_to_next_word_boundary(&SelectToNextWordBoundary, cx);
3463 assert_eq!(
3464 view.selection_ranges(cx),
3465 &[
3466 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3467 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
3468 ]
3469 );
3470 });
3471 }
3472
3473 #[gpui::test]
3474 fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
3475 let buffer =
3476 cx.add_model(|cx| Buffer::new(0, "use one::{\n two::three::four::five\n};", cx));
3477 let settings = EditorSettings::test(&cx);
3478 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3479
3480 view.update(cx, |view, cx| {
3481 view.set_wrap_width(140., cx);
3482 assert_eq!(
3483 view.display_text(cx),
3484 "use one::{\n two::three::\n four::five\n};"
3485 );
3486
3487 view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx)
3488 .unwrap();
3489
3490 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3491 assert_eq!(
3492 view.selection_ranges(cx),
3493 &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
3494 );
3495
3496 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3497 assert_eq!(
3498 view.selection_ranges(cx),
3499 &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
3500 );
3501
3502 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3503 assert_eq!(
3504 view.selection_ranges(cx),
3505 &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
3506 );
3507
3508 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3509 assert_eq!(
3510 view.selection_ranges(cx),
3511 &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
3512 );
3513
3514 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3515 assert_eq!(
3516 view.selection_ranges(cx),
3517 &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
3518 );
3519
3520 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3521 assert_eq!(
3522 view.selection_ranges(cx),
3523 &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
3524 );
3525 });
3526 }
3527
3528 #[gpui::test]
3529 fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
3530 let buffer = cx.add_model(|cx| Buffer::new(0, "one two three four", cx));
3531 let settings = EditorSettings::test(&cx);
3532 let (_, view) = cx.add_window(Default::default(), |cx| {
3533 build_editor(buffer.clone(), settings, cx)
3534 });
3535
3536 view.update(cx, |view, cx| {
3537 view.select_display_ranges(
3538 &[
3539 // an empty selection - the preceding word fragment is deleted
3540 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3541 // characters selected - they are deleted
3542 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
3543 ],
3544 cx,
3545 )
3546 .unwrap();
3547 view.delete_to_previous_word_boundary(&DeleteToPreviousWordBoundary, cx);
3548 });
3549
3550 assert_eq!(buffer.read(cx).text(), "e two te four");
3551
3552 view.update(cx, |view, cx| {
3553 view.select_display_ranges(
3554 &[
3555 // an empty selection - the following word fragment is deleted
3556 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3557 // characters selected - they are deleted
3558 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
3559 ],
3560 cx,
3561 )
3562 .unwrap();
3563 view.delete_to_next_word_boundary(&DeleteToNextWordBoundary, cx);
3564 });
3565
3566 assert_eq!(buffer.read(cx).text(), "e t te our");
3567 }
3568
3569 #[gpui::test]
3570 fn test_backspace(cx: &mut gpui::MutableAppContext) {
3571 let buffer = cx.add_model(|cx| {
3572 Buffer::new(
3573 0,
3574 "one two three\nfour five six\nseven eight nine\nten\n",
3575 cx,
3576 )
3577 });
3578 let settings = EditorSettings::test(&cx);
3579 let (_, view) = cx.add_window(Default::default(), |cx| {
3580 build_editor(buffer.clone(), settings, cx)
3581 });
3582
3583 view.update(cx, |view, cx| {
3584 view.select_display_ranges(
3585 &[
3586 // an empty selection - the preceding character is deleted
3587 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3588 // one character selected - it is deleted
3589 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3590 // a line suffix selected - it is deleted
3591 DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
3592 ],
3593 cx,
3594 )
3595 .unwrap();
3596 view.backspace(&Backspace, cx);
3597 });
3598
3599 assert_eq!(
3600 buffer.read(cx).text(),
3601 "oe two three\nfou five six\nseven ten\n"
3602 );
3603 }
3604
3605 #[gpui::test]
3606 fn test_delete(cx: &mut gpui::MutableAppContext) {
3607 let buffer = cx.add_model(|cx| {
3608 Buffer::new(
3609 0,
3610 "one two three\nfour five six\nseven eight nine\nten\n",
3611 cx,
3612 )
3613 });
3614 let settings = EditorSettings::test(&cx);
3615 let (_, view) = cx.add_window(Default::default(), |cx| {
3616 build_editor(buffer.clone(), settings, cx)
3617 });
3618
3619 view.update(cx, |view, cx| {
3620 view.select_display_ranges(
3621 &[
3622 // an empty selection - the following character is deleted
3623 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3624 // one character selected - it is deleted
3625 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3626 // a line suffix selected - it is deleted
3627 DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
3628 ],
3629 cx,
3630 )
3631 .unwrap();
3632 view.delete(&Delete, cx);
3633 });
3634
3635 assert_eq!(
3636 buffer.read(cx).text(),
3637 "on two three\nfou five six\nseven ten\n"
3638 );
3639 }
3640
3641 #[gpui::test]
3642 fn test_delete_line(cx: &mut gpui::MutableAppContext) {
3643 let settings = EditorSettings::test(&cx);
3644 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
3645 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3646 view.update(cx, |view, cx| {
3647 view.select_display_ranges(
3648 &[
3649 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3650 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
3651 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3652 ],
3653 cx,
3654 )
3655 .unwrap();
3656 view.delete_line(&DeleteLine, cx);
3657 assert_eq!(view.display_text(cx), "ghi");
3658 assert_eq!(
3659 view.selection_ranges(cx),
3660 vec![
3661 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3662 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
3663 ]
3664 );
3665 });
3666
3667 let settings = EditorSettings::test(&cx);
3668 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
3669 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3670 view.update(cx, |view, cx| {
3671 view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx)
3672 .unwrap();
3673 view.delete_line(&DeleteLine, cx);
3674 assert_eq!(view.display_text(cx), "ghi\n");
3675 assert_eq!(
3676 view.selection_ranges(cx),
3677 vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
3678 );
3679 });
3680 }
3681
3682 #[gpui::test]
3683 fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
3684 let settings = EditorSettings::test(&cx);
3685 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
3686 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3687 view.update(cx, |view, cx| {
3688 view.select_display_ranges(
3689 &[
3690 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3691 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3692 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3693 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3694 ],
3695 cx,
3696 )
3697 .unwrap();
3698 view.duplicate_line(&DuplicateLine, cx);
3699 assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
3700 assert_eq!(
3701 view.selection_ranges(cx),
3702 vec![
3703 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
3704 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3705 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3706 DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
3707 ]
3708 );
3709 });
3710
3711 let settings = EditorSettings::test(&cx);
3712 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
3713 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3714 view.update(cx, |view, cx| {
3715 view.select_display_ranges(
3716 &[
3717 DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
3718 DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
3719 ],
3720 cx,
3721 )
3722 .unwrap();
3723 view.duplicate_line(&DuplicateLine, cx);
3724 assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
3725 assert_eq!(
3726 view.selection_ranges(cx),
3727 vec![
3728 DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
3729 DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
3730 ]
3731 );
3732 });
3733 }
3734
3735 #[gpui::test]
3736 fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
3737 let settings = EditorSettings::test(&cx);
3738 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(10, 5), cx));
3739 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3740 view.update(cx, |view, cx| {
3741 view.fold_ranges(
3742 vec![
3743 Point::new(0, 2)..Point::new(1, 2),
3744 Point::new(2, 3)..Point::new(4, 1),
3745 Point::new(7, 0)..Point::new(8, 4),
3746 ],
3747 cx,
3748 );
3749 view.select_display_ranges(
3750 &[
3751 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3752 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3753 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3754 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
3755 ],
3756 cx,
3757 )
3758 .unwrap();
3759 assert_eq!(
3760 view.display_text(cx),
3761 "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
3762 );
3763
3764 view.move_line_up(&MoveLineUp, cx);
3765 assert_eq!(
3766 view.display_text(cx),
3767 "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
3768 );
3769 assert_eq!(
3770 view.selection_ranges(cx),
3771 vec![
3772 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3773 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3774 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
3775 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
3776 ]
3777 );
3778 });
3779
3780 view.update(cx, |view, cx| {
3781 view.move_line_down(&MoveLineDown, cx);
3782 assert_eq!(
3783 view.display_text(cx),
3784 "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
3785 );
3786 assert_eq!(
3787 view.selection_ranges(cx),
3788 vec![
3789 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3790 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3791 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3792 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
3793 ]
3794 );
3795 });
3796
3797 view.update(cx, |view, cx| {
3798 view.move_line_down(&MoveLineDown, cx);
3799 assert_eq!(
3800 view.display_text(cx),
3801 "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
3802 );
3803 assert_eq!(
3804 view.selection_ranges(cx),
3805 vec![
3806 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3807 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3808 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3809 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
3810 ]
3811 );
3812 });
3813
3814 view.update(cx, |view, cx| {
3815 view.move_line_up(&MoveLineUp, cx);
3816 assert_eq!(
3817 view.display_text(cx),
3818 "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
3819 );
3820 assert_eq!(
3821 view.selection_ranges(cx),
3822 vec![
3823 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3824 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3825 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
3826 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
3827 ]
3828 );
3829 });
3830 }
3831
3832 #[gpui::test]
3833 fn test_clipboard(cx: &mut gpui::MutableAppContext) {
3834 let buffer = cx.add_model(|cx| Buffer::new(0, "one✅ two three four five six ", cx));
3835 let settings = EditorSettings::test(&cx);
3836 let view = cx
3837 .add_window(Default::default(), |cx| {
3838 build_editor(buffer.clone(), settings, cx)
3839 })
3840 .1;
3841
3842 // Cut with three selections. Clipboard text is divided into three slices.
3843 view.update(cx, |view, cx| {
3844 view.select_ranges(vec![0..7, 11..17, 22..27], false, cx);
3845 view.cut(&Cut, cx);
3846 assert_eq!(view.display_text(cx), "two four six ");
3847 });
3848
3849 // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
3850 view.update(cx, |view, cx| {
3851 view.select_ranges(vec![4..4, 9..9, 13..13], false, cx);
3852 view.paste(&Paste, cx);
3853 assert_eq!(view.display_text(cx), "two one✅ four three six five ");
3854 assert_eq!(
3855 view.selection_ranges(cx),
3856 &[
3857 DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
3858 DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
3859 DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
3860 ]
3861 );
3862 });
3863
3864 // Paste again but with only two cursors. Since the number of cursors doesn't
3865 // match the number of slices in the clipboard, the entire clipboard text
3866 // is pasted at each cursor.
3867 view.update(cx, |view, cx| {
3868 view.select_ranges(vec![0..0, 31..31], false, cx);
3869 view.handle_input(&Input("( ".into()), cx);
3870 view.paste(&Paste, cx);
3871 view.handle_input(&Input(") ".into()), cx);
3872 assert_eq!(
3873 view.display_text(cx),
3874 "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
3875 );
3876 });
3877
3878 view.update(cx, |view, cx| {
3879 view.select_ranges(vec![0..0], false, cx);
3880 view.handle_input(&Input("123\n4567\n89\n".into()), cx);
3881 assert_eq!(
3882 view.display_text(cx),
3883 "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
3884 );
3885 });
3886
3887 // Cut with three selections, one of which is full-line.
3888 view.update(cx, |view, cx| {
3889 view.select_display_ranges(
3890 &[
3891 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
3892 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3893 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
3894 ],
3895 cx,
3896 )
3897 .unwrap();
3898 view.cut(&Cut, cx);
3899 assert_eq!(
3900 view.display_text(cx),
3901 "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
3902 );
3903 });
3904
3905 // Paste with three selections, noticing how the copied selection that was full-line
3906 // gets inserted before the second cursor.
3907 view.update(cx, |view, cx| {
3908 view.select_display_ranges(
3909 &[
3910 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3911 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3912 DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
3913 ],
3914 cx,
3915 )
3916 .unwrap();
3917 view.paste(&Paste, cx);
3918 assert_eq!(
3919 view.display_text(cx),
3920 "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
3921 );
3922 assert_eq!(
3923 view.selection_ranges(cx),
3924 &[
3925 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3926 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3927 DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
3928 ]
3929 );
3930 });
3931
3932 // Copy with a single cursor only, which writes the whole line into the clipboard.
3933 view.update(cx, |view, cx| {
3934 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx)
3935 .unwrap();
3936 view.copy(&Copy, cx);
3937 });
3938
3939 // Paste with three selections, noticing how the copied full-line selection is inserted
3940 // before the empty selections but replaces the selection that is non-empty.
3941 view.update(cx, |view, cx| {
3942 view.select_display_ranges(
3943 &[
3944 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3945 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
3946 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3947 ],
3948 cx,
3949 )
3950 .unwrap();
3951 view.paste(&Paste, cx);
3952 assert_eq!(
3953 view.display_text(cx),
3954 "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
3955 );
3956 assert_eq!(
3957 view.selection_ranges(cx),
3958 &[
3959 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3960 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3961 DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
3962 ]
3963 );
3964 });
3965 }
3966
3967 #[gpui::test]
3968 fn test_select_all(cx: &mut gpui::MutableAppContext) {
3969 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\nde\nfgh", cx));
3970 let settings = EditorSettings::test(&cx);
3971 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3972 view.update(cx, |view, cx| {
3973 view.select_all(&SelectAll, cx);
3974 assert_eq!(
3975 view.selection_ranges(cx),
3976 &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
3977 );
3978 });
3979 }
3980
3981 #[gpui::test]
3982 fn test_select_line(cx: &mut gpui::MutableAppContext) {
3983 let settings = EditorSettings::test(&cx);
3984 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 5), cx));
3985 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3986 view.update(cx, |view, cx| {
3987 view.select_display_ranges(
3988 &[
3989 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3990 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3991 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3992 DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
3993 ],
3994 cx,
3995 )
3996 .unwrap();
3997 view.select_line(&SelectLine, cx);
3998 assert_eq!(
3999 view.selection_ranges(cx),
4000 vec![
4001 DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
4002 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
4003 ]
4004 );
4005 });
4006
4007 view.update(cx, |view, cx| {
4008 view.select_line(&SelectLine, cx);
4009 assert_eq!(
4010 view.selection_ranges(cx),
4011 vec![
4012 DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
4013 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
4014 ]
4015 );
4016 });
4017
4018 view.update(cx, |view, cx| {
4019 view.select_line(&SelectLine, cx);
4020 assert_eq!(
4021 view.selection_ranges(cx),
4022 vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
4023 );
4024 });
4025 }
4026
4027 #[gpui::test]
4028 fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
4029 let settings = EditorSettings::test(&cx);
4030 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(9, 5), cx));
4031 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4032 view.update(cx, |view, cx| {
4033 view.fold_ranges(
4034 vec![
4035 Point::new(0, 2)..Point::new(1, 2),
4036 Point::new(2, 3)..Point::new(4, 1),
4037 Point::new(7, 0)..Point::new(8, 4),
4038 ],
4039 cx,
4040 );
4041 view.select_display_ranges(
4042 &[
4043 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4044 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4045 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4046 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
4047 ],
4048 cx,
4049 )
4050 .unwrap();
4051 assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
4052 });
4053
4054 view.update(cx, |view, cx| {
4055 view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
4056 assert_eq!(
4057 view.display_text(cx),
4058 "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
4059 );
4060 assert_eq!(
4061 view.selection_ranges(cx),
4062 [
4063 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4064 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4065 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
4066 DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
4067 ]
4068 );
4069 });
4070
4071 view.update(cx, |view, cx| {
4072 view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx)
4073 .unwrap();
4074 view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
4075 assert_eq!(
4076 view.display_text(cx),
4077 "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
4078 );
4079 assert_eq!(
4080 view.selection_ranges(cx),
4081 [
4082 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4083 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
4084 DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
4085 DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
4086 DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
4087 DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
4088 DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
4089 DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
4090 ]
4091 );
4092 });
4093 }
4094
4095 #[gpui::test]
4096 fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
4097 let settings = EditorSettings::test(&cx);
4098 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndefghi\n\njk\nlmno\n", cx));
4099 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4100
4101 view.update(cx, |view, cx| {
4102 view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx)
4103 .unwrap();
4104 });
4105 view.update(cx, |view, cx| {
4106 view.add_selection_above(&AddSelectionAbove, cx);
4107 assert_eq!(
4108 view.selection_ranges(cx),
4109 vec![
4110 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4111 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
4112 ]
4113 );
4114 });
4115
4116 view.update(cx, |view, cx| {
4117 view.add_selection_above(&AddSelectionAbove, cx);
4118 assert_eq!(
4119 view.selection_ranges(cx),
4120 vec![
4121 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4122 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
4123 ]
4124 );
4125 });
4126
4127 view.update(cx, |view, cx| {
4128 view.add_selection_below(&AddSelectionBelow, cx);
4129 assert_eq!(
4130 view.selection_ranges(cx),
4131 vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
4132 );
4133 });
4134
4135 view.update(cx, |view, cx| {
4136 view.add_selection_below(&AddSelectionBelow, cx);
4137 assert_eq!(
4138 view.selection_ranges(cx),
4139 vec![
4140 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
4141 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
4142 ]
4143 );
4144 });
4145
4146 view.update(cx, |view, cx| {
4147 view.add_selection_below(&AddSelectionBelow, cx);
4148 assert_eq!(
4149 view.selection_ranges(cx),
4150 vec![
4151 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
4152 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
4153 ]
4154 );
4155 });
4156
4157 view.update(cx, |view, cx| {
4158 view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx)
4159 .unwrap();
4160 });
4161 view.update(cx, |view, cx| {
4162 view.add_selection_below(&AddSelectionBelow, cx);
4163 assert_eq!(
4164 view.selection_ranges(cx),
4165 vec![
4166 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4167 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
4168 ]
4169 );
4170 });
4171
4172 view.update(cx, |view, cx| {
4173 view.add_selection_below(&AddSelectionBelow, cx);
4174 assert_eq!(
4175 view.selection_ranges(cx),
4176 vec![
4177 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4178 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
4179 ]
4180 );
4181 });
4182
4183 view.update(cx, |view, cx| {
4184 view.add_selection_above(&AddSelectionAbove, cx);
4185 assert_eq!(
4186 view.selection_ranges(cx),
4187 vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
4188 );
4189 });
4190
4191 view.update(cx, |view, cx| {
4192 view.add_selection_above(&AddSelectionAbove, cx);
4193 assert_eq!(
4194 view.selection_ranges(cx),
4195 vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
4196 );
4197 });
4198
4199 view.update(cx, |view, cx| {
4200 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx)
4201 .unwrap();
4202 view.add_selection_below(&AddSelectionBelow, cx);
4203 assert_eq!(
4204 view.selection_ranges(cx),
4205 vec![
4206 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4207 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4208 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4209 ]
4210 );
4211 });
4212
4213 view.update(cx, |view, cx| {
4214 view.add_selection_below(&AddSelectionBelow, cx);
4215 assert_eq!(
4216 view.selection_ranges(cx),
4217 vec![
4218 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4219 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4220 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4221 DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
4222 ]
4223 );
4224 });
4225
4226 view.update(cx, |view, cx| {
4227 view.add_selection_above(&AddSelectionAbove, cx);
4228 assert_eq!(
4229 view.selection_ranges(cx),
4230 vec![
4231 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4232 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4233 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4234 ]
4235 );
4236 });
4237
4238 view.update(cx, |view, cx| {
4239 view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx)
4240 .unwrap();
4241 });
4242 view.update(cx, |view, cx| {
4243 view.add_selection_above(&AddSelectionAbove, cx);
4244 assert_eq!(
4245 view.selection_ranges(cx),
4246 vec![
4247 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
4248 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
4249 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
4250 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
4251 ]
4252 );
4253 });
4254
4255 view.update(cx, |view, cx| {
4256 view.add_selection_below(&AddSelectionBelow, cx);
4257 assert_eq!(
4258 view.selection_ranges(cx),
4259 vec![
4260 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
4261 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
4262 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
4263 ]
4264 );
4265 });
4266 }
4267
4268 #[gpui::test]
4269 async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) {
4270 let settings = cx.read(EditorSettings::test);
4271 let language = Arc::new(Language::new(
4272 LanguageConfig::default(),
4273 tree_sitter_rust::language(),
4274 ));
4275
4276 let text = r#"
4277 use mod1::mod2::{mod3, mod4};
4278
4279 fn fn_1(param1: bool, param2: &str) {
4280 let var1 = "text";
4281 }
4282 "#
4283 .unindent();
4284
4285 let buffer = cx.add_model(|cx| {
4286 let history = History::new(text.into());
4287 Buffer::from_history(0, history, None, Some(language), cx)
4288 });
4289 let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
4290 view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
4291 .await;
4292
4293 view.update(&mut cx, |view, cx| {
4294 view.select_display_ranges(
4295 &[
4296 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4297 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4298 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4299 ],
4300 cx,
4301 )
4302 .unwrap();
4303 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4304 });
4305 assert_eq!(
4306 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4307 &[
4308 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
4309 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4310 DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
4311 ]
4312 );
4313
4314 view.update(&mut cx, |view, cx| {
4315 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4316 });
4317 assert_eq!(
4318 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4319 &[
4320 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4321 DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
4322 ]
4323 );
4324
4325 view.update(&mut cx, |view, cx| {
4326 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4327 });
4328 assert_eq!(
4329 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4330 &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
4331 );
4332
4333 // Trying to expand the selected syntax node one more time has no effect.
4334 view.update(&mut cx, |view, cx| {
4335 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4336 });
4337 assert_eq!(
4338 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4339 &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
4340 );
4341
4342 view.update(&mut cx, |view, cx| {
4343 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4344 });
4345 assert_eq!(
4346 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4347 &[
4348 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4349 DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
4350 ]
4351 );
4352
4353 view.update(&mut cx, |view, cx| {
4354 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4355 });
4356 assert_eq!(
4357 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4358 &[
4359 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
4360 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4361 DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
4362 ]
4363 );
4364
4365 view.update(&mut cx, |view, cx| {
4366 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4367 });
4368 assert_eq!(
4369 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4370 &[
4371 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4372 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4373 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4374 ]
4375 );
4376
4377 // Trying to shrink the selected syntax node one more time has no effect.
4378 view.update(&mut cx, |view, cx| {
4379 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4380 });
4381 assert_eq!(
4382 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4383 &[
4384 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4385 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4386 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4387 ]
4388 );
4389
4390 // Ensure that we keep expanding the selection if the larger selection starts or ends within
4391 // a fold.
4392 view.update(&mut cx, |view, cx| {
4393 view.fold_ranges(
4394 vec![
4395 Point::new(0, 21)..Point::new(0, 24),
4396 Point::new(3, 20)..Point::new(3, 22),
4397 ],
4398 cx,
4399 );
4400 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4401 });
4402 assert_eq!(
4403 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4404 &[
4405 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4406 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4407 DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
4408 ]
4409 );
4410 }
4411
4412 #[gpui::test]
4413 async fn test_autoclose_pairs(mut cx: gpui::TestAppContext) {
4414 let settings = cx.read(EditorSettings::test);
4415 let language = Arc::new(Language::new(
4416 LanguageConfig {
4417 autoclose_pairs: vec![
4418 AutoclosePair {
4419 start: "{".to_string(),
4420 end: "}".to_string(),
4421 },
4422 AutoclosePair {
4423 start: "/*".to_string(),
4424 end: " */".to_string(),
4425 },
4426 ],
4427 ..Default::default()
4428 },
4429 tree_sitter_rust::language(),
4430 ));
4431
4432 let text = r#"
4433 a
4434
4435 /
4436
4437 "#
4438 .unindent();
4439
4440 let buffer = cx.add_model(|cx| {
4441 let history = History::new(text.into());
4442 Buffer::from_history(0, history, None, Some(language), cx)
4443 });
4444 let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
4445 view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
4446 .await;
4447
4448 view.update(&mut cx, |view, cx| {
4449 view.select_display_ranges(
4450 &[
4451 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4452 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4453 ],
4454 cx,
4455 )
4456 .unwrap();
4457 view.handle_input(&Input("{".to_string()), cx);
4458 view.handle_input(&Input("{".to_string()), cx);
4459 view.handle_input(&Input("{".to_string()), cx);
4460 assert_eq!(
4461 view.text(cx),
4462 "
4463 {{{}}}
4464 {{{}}}
4465 /
4466
4467 "
4468 .unindent()
4469 );
4470
4471 view.move_right(&MoveRight, cx);
4472 view.handle_input(&Input("}".to_string()), cx);
4473 view.handle_input(&Input("}".to_string()), cx);
4474 view.handle_input(&Input("}".to_string()), cx);
4475 assert_eq!(
4476 view.text(cx),
4477 "
4478 {{{}}}}
4479 {{{}}}}
4480 /
4481
4482 "
4483 .unindent()
4484 );
4485
4486 view.undo(&Undo, cx);
4487 view.handle_input(&Input("/".to_string()), cx);
4488 view.handle_input(&Input("*".to_string()), cx);
4489 assert_eq!(
4490 view.text(cx),
4491 "
4492 /* */
4493 /* */
4494 /
4495
4496 "
4497 .unindent()
4498 );
4499
4500 view.undo(&Undo, cx);
4501 view.select_display_ranges(
4502 &[
4503 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4504 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4505 ],
4506 cx,
4507 )
4508 .unwrap();
4509 view.handle_input(&Input("*".to_string()), cx);
4510 assert_eq!(
4511 view.text(cx),
4512 "
4513 a
4514
4515 /*
4516 *
4517 "
4518 .unindent()
4519 );
4520 });
4521 }
4522
4523 impl Editor {
4524 fn selection_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
4525 self.selections_in_range(
4526 self.selection_set_id,
4527 DisplayPoint::zero()..self.max_point(cx),
4528 cx,
4529 )
4530 .collect::<Vec<_>>()
4531 }
4532 }
4533
4534 fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
4535 let point = DisplayPoint::new(row as u32, column as u32);
4536 point..point
4537 }
4538
4539 fn build_editor(
4540 buffer: ModelHandle<Buffer>,
4541 settings: EditorSettings,
4542 cx: &mut ViewContext<Editor>,
4543 ) -> Editor {
4544 Editor::for_buffer(buffer, move |_| settings.clone(), cx)
4545 }
4546}
4547
4548trait RangeExt<T> {
4549 fn sorted(&self) -> Range<T>;
4550 fn to_inclusive(&self) -> RangeInclusive<T>;
4551}
4552
4553impl<T: Ord + Clone> RangeExt<T> for Range<T> {
4554 fn sorted(&self) -> Self {
4555 cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
4556 }
4557
4558 fn to_inclusive(&self) -> RangeInclusive<T> {
4559 self.start.clone()..=self.end.clone()
4560 }
4561}