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