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