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