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