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