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