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 for row in selection.start.row..selection.end.row {
2007 let cursor = Point::new(row, buffer.line_len(row));
2008 new_selections.push(Selection {
2009 id: post_inc(&mut self.next_selection_id),
2010 start: cursor,
2011 end: cursor,
2012 reversed: false,
2013 goal: SelectionGoal::None,
2014 });
2015 }
2016 new_selections.push(Selection {
2017 id: selection.id,
2018 start: selection.end,
2019 end: selection.end,
2020 reversed: false,
2021 goal: SelectionGoal::None,
2022 });
2023 to_unfold.push(selection.start..selection.end);
2024 }
2025 self.unfold_ranges(to_unfold, cx);
2026 self.update_selections(new_selections, true, cx);
2027 }
2028
2029 pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
2030 self.add_selection(true, cx);
2031 }
2032
2033 pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
2034 self.add_selection(false, cx);
2035 }
2036
2037 fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
2038 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2039 let mut selections = self.selections::<Point>(cx).collect::<Vec<_>>();
2040 let mut state = self.add_selections_state.take().unwrap_or_else(|| {
2041 let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
2042 let range = oldest_selection.display_range(&display_map).sorted();
2043 let columns = cmp::min(range.start.column(), range.end.column())
2044 ..cmp::max(range.start.column(), range.end.column());
2045
2046 selections.clear();
2047 let mut stack = Vec::new();
2048 for row in range.start.row()..=range.end.row() {
2049 if let Some(selection) = self.build_columnar_selection(
2050 &display_map,
2051 row,
2052 &columns,
2053 oldest_selection.reversed,
2054 ) {
2055 stack.push(selection.id);
2056 selections.push(selection);
2057 }
2058 }
2059
2060 if above {
2061 stack.reverse();
2062 }
2063
2064 AddSelectionsState { above, stack }
2065 });
2066
2067 let last_added_selection = *state.stack.last().unwrap();
2068 let mut new_selections = Vec::new();
2069 if above == state.above {
2070 let end_row = if above {
2071 0
2072 } else {
2073 display_map.max_point().row()
2074 };
2075
2076 'outer: for selection in selections {
2077 if selection.id == last_added_selection {
2078 let range = selection.display_range(&display_map).sorted();
2079 debug_assert_eq!(range.start.row(), range.end.row());
2080 let mut row = range.start.row();
2081 let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
2082 {
2083 start..end
2084 } else {
2085 cmp::min(range.start.column(), range.end.column())
2086 ..cmp::max(range.start.column(), range.end.column())
2087 };
2088
2089 while row != end_row {
2090 if above {
2091 row -= 1;
2092 } else {
2093 row += 1;
2094 }
2095
2096 if let Some(new_selection) = self.build_columnar_selection(
2097 &display_map,
2098 row,
2099 &columns,
2100 selection.reversed,
2101 ) {
2102 state.stack.push(new_selection.id);
2103 if above {
2104 new_selections.push(new_selection);
2105 new_selections.push(selection);
2106 } else {
2107 new_selections.push(selection);
2108 new_selections.push(new_selection);
2109 }
2110
2111 continue 'outer;
2112 }
2113 }
2114 }
2115
2116 new_selections.push(selection);
2117 }
2118 } else {
2119 new_selections = selections;
2120 new_selections.retain(|s| s.id != last_added_selection);
2121 state.stack.pop();
2122 }
2123
2124 self.update_selections(new_selections, true, cx);
2125 if state.stack.len() > 1 {
2126 self.add_selections_state = Some(state);
2127 }
2128 }
2129
2130 pub fn select_larger_syntax_node(
2131 &mut self,
2132 _: &SelectLargerSyntaxNode,
2133 cx: &mut ViewContext<Self>,
2134 ) {
2135 let old_selections = self.selections::<usize>(cx).collect::<Box<_>>();
2136 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2137 let buffer = self.buffer.read(cx);
2138
2139 let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2140 let mut selected_larger_node = false;
2141 let mut new_selections = old_selections
2142 .iter()
2143 .map(|selection| {
2144 let old_range = selection.start..selection.end;
2145 let mut new_range = old_range.clone();
2146 while let Some(containing_range) =
2147 buffer.range_for_syntax_ancestor(new_range.clone())
2148 {
2149 new_range = containing_range;
2150 if !display_map.intersects_fold(new_range.start)
2151 && !display_map.intersects_fold(new_range.end)
2152 {
2153 break;
2154 }
2155 }
2156
2157 selected_larger_node |= new_range != old_range;
2158 Selection {
2159 id: selection.id,
2160 start: new_range.start,
2161 end: new_range.end,
2162 goal: SelectionGoal::None,
2163 reversed: selection.reversed,
2164 }
2165 })
2166 .collect::<Vec<_>>();
2167
2168 if selected_larger_node {
2169 stack.push(old_selections);
2170 new_selections.sort_unstable_by_key(|selection| selection.start);
2171 self.update_selections(new_selections, true, cx);
2172 }
2173 self.select_larger_syntax_node_stack = stack;
2174 }
2175
2176 pub fn select_smaller_syntax_node(
2177 &mut self,
2178 _: &SelectSmallerSyntaxNode,
2179 cx: &mut ViewContext<Self>,
2180 ) {
2181 let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2182 if let Some(selections) = stack.pop() {
2183 self.update_selections(selections.to_vec(), true, cx);
2184 }
2185 self.select_larger_syntax_node_stack = stack;
2186 }
2187
2188 pub fn move_to_enclosing_bracket(
2189 &mut self,
2190 _: &MoveToEnclosingBracket,
2191 cx: &mut ViewContext<Self>,
2192 ) {
2193 let mut selections = self.selections::<usize>(cx).collect::<Vec<_>>();
2194 let buffer = self.buffer.read(cx.as_ref());
2195 for selection in &mut selections {
2196 if let Some((open_range, close_range)) =
2197 buffer.enclosing_bracket_ranges(selection.start..selection.end)
2198 {
2199 let close_range = close_range.to_inclusive();
2200 let destination = if close_range.contains(&selection.start)
2201 && close_range.contains(&selection.end)
2202 {
2203 open_range.end
2204 } else {
2205 *close_range.start()
2206 };
2207 selection.start = destination;
2208 selection.end = destination;
2209 }
2210 }
2211
2212 self.update_selections(selections, true, cx);
2213 }
2214
2215 pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
2216 let selection = self.newest_selection::<usize>(cx);
2217 let buffer = self.buffer.read(cx.as_ref());
2218 let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
2219 active_diagnostics
2220 .primary_range
2221 .to_offset(buffer)
2222 .to_inclusive()
2223 });
2224 let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
2225 if active_primary_range.contains(&selection.head()) {
2226 *active_primary_range.end()
2227 } else {
2228 selection.head()
2229 }
2230 } else {
2231 selection.head()
2232 };
2233
2234 loop {
2235 let next_group = buffer
2236 .diagnostics_in_range::<_, usize>(search_start..buffer.len())
2237 .find_map(|(range, diagnostic)| {
2238 if diagnostic.is_primary
2239 && !range.is_empty()
2240 && Some(range.end) != active_primary_range.as_ref().map(|r| *r.end())
2241 {
2242 Some((range, diagnostic.group_id))
2243 } else {
2244 None
2245 }
2246 });
2247
2248 if let Some((primary_range, group_id)) = next_group {
2249 self.activate_diagnostics(group_id, cx);
2250 self.update_selections(
2251 vec![Selection {
2252 id: selection.id,
2253 start: primary_range.start,
2254 end: primary_range.start,
2255 reversed: false,
2256 goal: SelectionGoal::None,
2257 }],
2258 true,
2259 cx,
2260 );
2261 break;
2262 } else if search_start == 0 {
2263 break;
2264 } else {
2265 // Cycle around to the start of the buffer.
2266 search_start = 0;
2267 }
2268 }
2269 }
2270
2271 fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
2272 if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
2273 let buffer = self.buffer.read(cx);
2274 let primary_range_start = active_diagnostics.primary_range.start.to_offset(buffer);
2275 let is_valid = buffer
2276 .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone())
2277 .any(|(range, diagnostic)| {
2278 diagnostic.is_primary
2279 && !range.is_empty()
2280 && range.start == primary_range_start
2281 && diagnostic.message == active_diagnostics.primary_message
2282 });
2283
2284 if is_valid != active_diagnostics.is_valid {
2285 active_diagnostics.is_valid = is_valid;
2286 let mut new_styles = HashMap::new();
2287 for (block_id, diagnostic) in &active_diagnostics.blocks {
2288 let severity = diagnostic.severity;
2289 let message_len = diagnostic.message.len();
2290 new_styles.insert(
2291 *block_id,
2292 (
2293 Some({
2294 let build_settings = self.build_settings.clone();
2295 move |cx: &AppContext| {
2296 let settings = build_settings.borrow()(cx);
2297 vec![(
2298 message_len,
2299 diagnostic_style(severity, is_valid, &settings.style)
2300 .text
2301 .into(),
2302 )]
2303 }
2304 }),
2305 Some({
2306 let build_settings = self.build_settings.clone();
2307 move |cx: &AppContext| {
2308 let settings = build_settings.borrow()(cx);
2309 diagnostic_style(severity, is_valid, &settings.style).block
2310 }
2311 }),
2312 ),
2313 );
2314 }
2315 self.display_map
2316 .update(cx, |display_map, _| display_map.restyle_blocks(new_styles));
2317 }
2318 }
2319 }
2320
2321 fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
2322 self.dismiss_diagnostics(cx);
2323 self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
2324 let buffer = self.buffer.read(cx);
2325
2326 let mut primary_range = None;
2327 let mut primary_message = None;
2328 let mut group_end = Point::zero();
2329 let diagnostic_group = buffer
2330 .diagnostic_group::<Point>(group_id)
2331 .map(|(range, diagnostic)| {
2332 if range.end > group_end {
2333 group_end = range.end;
2334 }
2335 if diagnostic.is_primary {
2336 primary_range = Some(range.clone());
2337 primary_message = Some(diagnostic.message.clone());
2338 }
2339 (range, diagnostic.clone())
2340 })
2341 .collect::<Vec<_>>();
2342 let primary_range = primary_range.unwrap();
2343 let primary_message = primary_message.unwrap();
2344 let primary_range =
2345 buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
2346
2347 let blocks = display_map
2348 .insert_blocks(
2349 diagnostic_group.iter().map(|(range, diagnostic)| {
2350 let build_settings = self.build_settings.clone();
2351 let message_len = diagnostic.message.len();
2352 let severity = diagnostic.severity;
2353 BlockProperties {
2354 position: range.start,
2355 text: diagnostic.message.as_str(),
2356 build_runs: Some(Arc::new({
2357 let build_settings = build_settings.clone();
2358 move |cx| {
2359 let settings = build_settings.borrow()(cx);
2360 vec![(
2361 message_len,
2362 diagnostic_style(severity, true, &settings.style)
2363 .text
2364 .into(),
2365 )]
2366 }
2367 })),
2368 build_style: Some(Arc::new({
2369 let build_settings = build_settings.clone();
2370 move |cx| {
2371 let settings = build_settings.borrow()(cx);
2372 diagnostic_style(severity, true, &settings.style).block
2373 }
2374 })),
2375 disposition: BlockDisposition::Below,
2376 }
2377 }),
2378 cx,
2379 )
2380 .into_iter()
2381 .zip(
2382 diagnostic_group
2383 .into_iter()
2384 .map(|(_, diagnostic)| diagnostic),
2385 )
2386 .collect();
2387
2388 Some(ActiveDiagnosticGroup {
2389 primary_range,
2390 primary_message,
2391 blocks,
2392 is_valid: true,
2393 })
2394 });
2395 }
2396
2397 fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
2398 if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
2399 self.display_map.update(cx, |display_map, cx| {
2400 display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
2401 });
2402 cx.notify();
2403 }
2404 }
2405
2406 fn build_columnar_selection(
2407 &mut self,
2408 display_map: &DisplayMapSnapshot,
2409 row: u32,
2410 columns: &Range<u32>,
2411 reversed: bool,
2412 ) -> Option<Selection<Point>> {
2413 let is_empty = columns.start == columns.end;
2414 let line_len = display_map.line_len(row);
2415 if columns.start < line_len || (is_empty && columns.start == line_len) {
2416 let start = DisplayPoint::new(row, columns.start);
2417 let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
2418 Some(Selection {
2419 id: post_inc(&mut self.next_selection_id),
2420 start: start.to_point(display_map),
2421 end: end.to_point(display_map),
2422 reversed,
2423 goal: SelectionGoal::ColumnRange {
2424 start: columns.start,
2425 end: columns.end,
2426 },
2427 })
2428 } else {
2429 None
2430 }
2431 }
2432
2433 pub fn active_selection_sets<'a>(
2434 &'a self,
2435 cx: &'a AppContext,
2436 ) -> impl 'a + Iterator<Item = SelectionSetId> {
2437 let buffer = self.buffer.read(cx);
2438 let replica_id = buffer.replica_id();
2439 buffer
2440 .selection_sets()
2441 .filter(move |(set_id, set)| {
2442 set.active && (set_id.replica_id != replica_id || **set_id == self.selection_set_id)
2443 })
2444 .map(|(set_id, _)| *set_id)
2445 }
2446
2447 pub fn selections_in_range<'a>(
2448 &'a self,
2449 set_id: SelectionSetId,
2450 range: Range<DisplayPoint>,
2451 cx: &'a mut MutableAppContext,
2452 ) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
2453 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2454 let buffer = self.buffer.read(cx);
2455 let selections = self
2456 .buffer
2457 .read(cx)
2458 .selection_set(set_id)
2459 .unwrap()
2460 .selections::<Point, _>(buffer)
2461 .collect::<Vec<_>>();
2462 let start = range.start.to_point(&display_map);
2463 let start_index = self.selection_insertion_index(&selections, start);
2464 let pending_selection = if set_id == self.selection_set_id {
2465 self.pending_selection.as_ref().and_then(|pending| {
2466 let mut selection_start = pending.start.to_display_point(&display_map);
2467 let mut selection_end = pending.end.to_display_point(&display_map);
2468 if pending.reversed {
2469 mem::swap(&mut selection_start, &mut selection_end);
2470 }
2471 if selection_start <= range.end || selection_end <= range.end {
2472 Some(selection_start..selection_end)
2473 } else {
2474 None
2475 }
2476 })
2477 } else {
2478 None
2479 };
2480 selections
2481 .into_iter()
2482 .skip(start_index)
2483 .map(move |s| s.display_range(&display_map))
2484 .take_while(move |r| r.start <= range.end || r.end <= range.end)
2485 .chain(pending_selection)
2486 }
2487
2488 fn selection_insertion_index(&self, selections: &[Selection<Point>], start: Point) -> usize {
2489 match selections.binary_search_by_key(&start, |probe| probe.start) {
2490 Ok(index) => index,
2491 Err(index) => {
2492 if index > 0 && selections[index - 1].end > start {
2493 index - 1
2494 } else {
2495 index
2496 }
2497 }
2498 }
2499 }
2500
2501 pub fn selections<'a, D>(&self, cx: &'a AppContext) -> impl 'a + Iterator<Item = Selection<D>>
2502 where
2503 D: 'a + TextDimension<'a> + Ord,
2504 {
2505 let buffer = self.buffer.read(cx);
2506 let mut selections = self.selection_set(cx).selections::<D, _>(buffer).peekable();
2507 let mut pending_selection = self.pending_selection(cx);
2508 iter::from_fn(move || {
2509 if let Some(pending) = pending_selection.as_mut() {
2510 while let Some(next_selection) = selections.peek() {
2511 if pending.start <= next_selection.end && pending.end >= next_selection.start {
2512 let next_selection = selections.next().unwrap();
2513 if next_selection.start < pending.start {
2514 pending.start = next_selection.start;
2515 }
2516 if next_selection.end > pending.end {
2517 pending.end = next_selection.end;
2518 }
2519 } else if next_selection.end < pending.start {
2520 return selections.next();
2521 } else {
2522 break;
2523 }
2524 }
2525
2526 pending_selection.take()
2527 } else {
2528 selections.next()
2529 }
2530 })
2531 }
2532
2533 fn pending_selection<'a, D>(&self, cx: &'a AppContext) -> Option<Selection<D>>
2534 where
2535 D: 'a + TextDimension<'a>,
2536 {
2537 let buffer = self.buffer.read(cx);
2538 self.pending_selection.as_ref().map(|selection| Selection {
2539 id: selection.id,
2540 start: selection.start.summary::<D, _>(buffer),
2541 end: selection.end.summary::<D, _>(buffer),
2542 reversed: selection.reversed,
2543 goal: selection.goal,
2544 })
2545 }
2546
2547 fn selection_count<'a>(&self, cx: &'a AppContext) -> usize {
2548 let mut selection_count = self.selection_set(cx).len();
2549 if self.pending_selection.is_some() {
2550 selection_count += 1;
2551 }
2552 selection_count
2553 }
2554
2555 pub fn oldest_selection<'a, T>(&self, cx: &'a AppContext) -> Selection<T>
2556 where
2557 T: 'a + TextDimension<'a>,
2558 {
2559 let buffer = self.buffer.read(cx);
2560 self.selection_set(cx)
2561 .oldest_selection(buffer)
2562 .or_else(|| self.pending_selection(cx))
2563 .unwrap()
2564 }
2565
2566 pub fn newest_selection<'a, T>(&self, cx: &'a AppContext) -> Selection<T>
2567 where
2568 T: 'a + TextDimension<'a>,
2569 {
2570 let buffer = self.buffer.read(cx);
2571 self.pending_selection(cx)
2572 .or_else(|| self.selection_set(cx).newest_selection(buffer))
2573 .unwrap()
2574 }
2575
2576 fn selection_set<'a>(&self, cx: &'a AppContext) -> &'a SelectionSet {
2577 self.buffer
2578 .read(cx)
2579 .selection_set(self.selection_set_id)
2580 .unwrap()
2581 }
2582
2583 fn update_selections<T>(
2584 &mut self,
2585 mut selections: Vec<Selection<T>>,
2586 autoscroll: bool,
2587 cx: &mut ViewContext<Self>,
2588 ) where
2589 T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
2590 {
2591 // Merge overlapping selections.
2592 let buffer = self.buffer.read(cx);
2593 let mut i = 1;
2594 while i < selections.len() {
2595 if selections[i - 1].end >= selections[i].start {
2596 let removed = selections.remove(i);
2597 if removed.start < selections[i - 1].start {
2598 selections[i - 1].start = removed.start;
2599 }
2600 if removed.end > selections[i - 1].end {
2601 selections[i - 1].end = removed.end;
2602 }
2603 } else {
2604 i += 1;
2605 }
2606 }
2607
2608 self.pending_selection = None;
2609 self.add_selections_state = None;
2610 self.select_larger_syntax_node_stack.clear();
2611 while let Some(autoclose_pair_state) = self.autoclose_stack.last() {
2612 let all_selections_inside_autoclose_ranges =
2613 if selections.len() == autoclose_pair_state.ranges.len() {
2614 selections
2615 .iter()
2616 .zip(autoclose_pair_state.ranges.ranges::<Point, _>(buffer))
2617 .all(|(selection, autoclose_range)| {
2618 let head = selection.head().to_point(&*buffer);
2619 autoclose_range.start <= head && autoclose_range.end >= head
2620 })
2621 } else {
2622 false
2623 };
2624
2625 if all_selections_inside_autoclose_ranges {
2626 break;
2627 } else {
2628 self.autoclose_stack.pop();
2629 }
2630 }
2631
2632 if autoscroll {
2633 self.request_autoscroll(cx);
2634 }
2635 self.pause_cursor_blinking(cx);
2636
2637 self.buffer.update(cx, |buffer, cx| {
2638 buffer
2639 .update_selection_set(self.selection_set_id, &selections, cx)
2640 .unwrap();
2641 });
2642 }
2643
2644 fn request_autoscroll(&mut self, cx: &mut ViewContext<Self>) {
2645 self.autoscroll_requested = true;
2646 cx.notify();
2647 }
2648
2649 fn start_transaction(&mut self, cx: &mut ViewContext<Self>) {
2650 self.end_selection(cx);
2651 self.buffer.update(cx, |buffer, _| {
2652 buffer
2653 .start_transaction(Some(self.selection_set_id))
2654 .unwrap()
2655 });
2656 }
2657
2658 fn end_transaction(&self, cx: &mut ViewContext<Self>) {
2659 self.buffer.update(cx, |buffer, cx| {
2660 buffer
2661 .end_transaction(Some(self.selection_set_id), cx)
2662 .unwrap()
2663 });
2664 }
2665
2666 pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
2667 log::info!("Editor::page_up");
2668 }
2669
2670 pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
2671 log::info!("Editor::page_down");
2672 }
2673
2674 pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
2675 let mut fold_ranges = Vec::new();
2676
2677 let selections = self.selections::<Point>(cx).collect::<Vec<_>>();
2678 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2679 for selection in selections {
2680 let range = selection.display_range(&display_map).sorted();
2681 let buffer_start_row = range.start.to_point(&display_map).row;
2682
2683 for row in (0..=range.end.row()).rev() {
2684 if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
2685 let fold_range = self.foldable_range_for_line(&display_map, row);
2686 if fold_range.end.row >= buffer_start_row {
2687 fold_ranges.push(fold_range);
2688 if row <= range.start.row() {
2689 break;
2690 }
2691 }
2692 }
2693 }
2694 }
2695
2696 self.fold_ranges(fold_ranges, cx);
2697 }
2698
2699 pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
2700 let selections = self.selections::<Point>(cx).collect::<Vec<_>>();
2701 let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2702 let buffer = self.buffer.read(cx);
2703 let ranges = selections
2704 .iter()
2705 .map(|s| {
2706 let range = s.display_range(&display_map).sorted();
2707 let mut start = range.start.to_point(&display_map);
2708 let mut end = range.end.to_point(&display_map);
2709 start.column = 0;
2710 end.column = buffer.line_len(end.row);
2711 start..end
2712 })
2713 .collect::<Vec<_>>();
2714 self.unfold_ranges(ranges, cx);
2715 }
2716
2717 fn is_line_foldable(&self, display_map: &DisplayMapSnapshot, display_row: u32) -> bool {
2718 let max_point = display_map.max_point();
2719 if display_row >= max_point.row() {
2720 false
2721 } else {
2722 let (start_indent, is_blank) = display_map.line_indent(display_row);
2723 if is_blank {
2724 false
2725 } else {
2726 for display_row in display_row + 1..=max_point.row() {
2727 let (indent, is_blank) = display_map.line_indent(display_row);
2728 if !is_blank {
2729 return indent > start_indent;
2730 }
2731 }
2732 false
2733 }
2734 }
2735 }
2736
2737 fn foldable_range_for_line(
2738 &self,
2739 display_map: &DisplayMapSnapshot,
2740 start_row: u32,
2741 ) -> Range<Point> {
2742 let max_point = display_map.max_point();
2743
2744 let (start_indent, _) = display_map.line_indent(start_row);
2745 let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
2746 let mut end = None;
2747 for row in start_row + 1..=max_point.row() {
2748 let (indent, is_blank) = display_map.line_indent(row);
2749 if !is_blank && indent <= start_indent {
2750 end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
2751 break;
2752 }
2753 }
2754
2755 let end = end.unwrap_or(max_point);
2756 return start.to_point(display_map)..end.to_point(display_map);
2757 }
2758
2759 pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
2760 let selections = self.selections::<Point>(cx);
2761 let ranges = selections.map(|s| s.start..s.end).collect();
2762 self.fold_ranges(ranges, cx);
2763 }
2764
2765 fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
2766 if !ranges.is_empty() {
2767 self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
2768 self.autoscroll_requested = true;
2769 cx.notify();
2770 }
2771 }
2772
2773 fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
2774 if !ranges.is_empty() {
2775 self.display_map
2776 .update(cx, |map, cx| map.unfold(ranges, cx));
2777 self.autoscroll_requested = true;
2778 cx.notify();
2779 }
2780 }
2781
2782 pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
2783 self.display_map
2784 .update(cx, |map, cx| map.snapshot(cx))
2785 .longest_row()
2786 }
2787
2788 pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
2789 self.display_map
2790 .update(cx, |map, cx| map.snapshot(cx))
2791 .max_point()
2792 }
2793
2794 pub fn text(&self, cx: &AppContext) -> String {
2795 self.buffer.read(cx).text()
2796 }
2797
2798 pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
2799 self.display_map
2800 .update(cx, |map, cx| map.snapshot(cx))
2801 .text()
2802 }
2803
2804 // pub fn font_size(&self) -> f32 {
2805 // self.settings.font_size
2806 // }
2807
2808 pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool {
2809 self.display_map
2810 .update(cx, |map, cx| map.set_wrap_width(Some(width), cx))
2811 }
2812
2813 fn next_blink_epoch(&mut self) -> usize {
2814 self.blink_epoch += 1;
2815 self.blink_epoch
2816 }
2817
2818 fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
2819 self.show_local_cursors = true;
2820 cx.notify();
2821
2822 let epoch = self.next_blink_epoch();
2823 cx.spawn(|this, mut cx| {
2824 let this = this.downgrade();
2825 async move {
2826 Timer::after(CURSOR_BLINK_INTERVAL).await;
2827 if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
2828 this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
2829 }
2830 }
2831 })
2832 .detach();
2833 }
2834
2835 fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
2836 if epoch == self.blink_epoch {
2837 self.blinking_paused = false;
2838 self.blink_cursors(epoch, cx);
2839 }
2840 }
2841
2842 fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
2843 if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
2844 self.show_local_cursors = !self.show_local_cursors;
2845 cx.notify();
2846
2847 let epoch = self.next_blink_epoch();
2848 cx.spawn(|this, mut cx| {
2849 let this = this.downgrade();
2850 async move {
2851 Timer::after(CURSOR_BLINK_INTERVAL).await;
2852 if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
2853 this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
2854 }
2855 }
2856 })
2857 .detach();
2858 }
2859 }
2860
2861 pub fn show_local_cursors(&self) -> bool {
2862 self.show_local_cursors
2863 }
2864
2865 fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, cx: &mut ViewContext<Self>) {
2866 self.refresh_active_diagnostics(cx);
2867 cx.notify();
2868 }
2869
2870 fn on_buffer_event(
2871 &mut self,
2872 _: ModelHandle<Buffer>,
2873 event: &language::Event,
2874 cx: &mut ViewContext<Self>,
2875 ) {
2876 match event {
2877 language::Event::Edited => cx.emit(Event::Edited),
2878 language::Event::Dirtied => cx.emit(Event::Dirtied),
2879 language::Event::Saved => cx.emit(Event::Saved),
2880 language::Event::FileHandleChanged => cx.emit(Event::FileHandleChanged),
2881 language::Event::Reloaded => cx.emit(Event::FileHandleChanged),
2882 language::Event::Closed => cx.emit(Event::Closed),
2883 language::Event::Reparsed => {}
2884 }
2885 }
2886
2887 fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
2888 cx.notify();
2889 }
2890}
2891
2892impl Snapshot {
2893 pub fn is_empty(&self) -> bool {
2894 self.display_snapshot.is_empty()
2895 }
2896
2897 pub fn is_focused(&self) -> bool {
2898 self.is_focused
2899 }
2900
2901 pub fn placeholder_text(&self) -> Option<&Arc<str>> {
2902 self.placeholder_text.as_ref()
2903 }
2904
2905 pub fn buffer_row_count(&self) -> u32 {
2906 self.display_snapshot.buffer_row_count()
2907 }
2908
2909 pub fn buffer_rows<'a>(&'a self, start_row: u32, cx: &'a AppContext) -> BufferRows<'a> {
2910 self.display_snapshot.buffer_rows(start_row, Some(cx))
2911 }
2912
2913 pub fn chunks<'a>(
2914 &'a self,
2915 display_rows: Range<u32>,
2916 theme: Option<&'a SyntaxTheme>,
2917 cx: &'a AppContext,
2918 ) -> display_map::Chunks<'a> {
2919 self.display_snapshot.chunks(display_rows, theme, cx)
2920 }
2921
2922 pub fn scroll_position(&self) -> Vector2F {
2923 compute_scroll_position(
2924 &self.display_snapshot,
2925 self.scroll_position,
2926 &self.scroll_top_anchor,
2927 )
2928 }
2929
2930 pub fn max_point(&self) -> DisplayPoint {
2931 self.display_snapshot.max_point()
2932 }
2933
2934 pub fn longest_row(&self) -> u32 {
2935 self.display_snapshot.longest_row()
2936 }
2937
2938 pub fn line_len(&self, display_row: u32) -> u32 {
2939 self.display_snapshot.line_len(display_row)
2940 }
2941
2942 pub fn line(&self, display_row: u32) -> String {
2943 self.display_snapshot.line(display_row)
2944 }
2945
2946 pub fn prev_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
2947 self.display_snapshot.prev_row_boundary(point)
2948 }
2949
2950 pub fn next_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
2951 self.display_snapshot.next_row_boundary(point)
2952 }
2953}
2954
2955impl EditorSettings {
2956 #[cfg(any(test, feature = "test-support"))]
2957 pub fn test(cx: &AppContext) -> Self {
2958 Self {
2959 tab_size: 4,
2960 style: {
2961 let font_cache: &gpui::FontCache = cx.font_cache();
2962 let font_family_name = Arc::from("Monaco");
2963 let font_properties = Default::default();
2964 let font_family_id = font_cache.load_family(&[&font_family_name]).unwrap();
2965 let font_id = font_cache
2966 .select_font(font_family_id, &font_properties)
2967 .unwrap();
2968 EditorStyle {
2969 text: gpui::fonts::TextStyle {
2970 font_family_name,
2971 font_family_id,
2972 font_id,
2973 font_size: 14.,
2974 color: gpui::color::Color::from_u32(0xff0000ff),
2975 font_properties,
2976 underline: None,
2977 },
2978 placeholder_text: None,
2979 background: Default::default(),
2980 gutter_background: Default::default(),
2981 active_line_background: Default::default(),
2982 line_number: Default::default(),
2983 line_number_active: Default::default(),
2984 selection: Default::default(),
2985 guest_selections: Default::default(),
2986 syntax: Default::default(),
2987 error_diagnostic: Default::default(),
2988 invalid_error_diagnostic: Default::default(),
2989 warning_diagnostic: Default::default(),
2990 invalid_warning_diagnostic: Default::default(),
2991 information_diagnostic: Default::default(),
2992 invalid_information_diagnostic: Default::default(),
2993 hint_diagnostic: Default::default(),
2994 invalid_hint_diagnostic: Default::default(),
2995 }
2996 },
2997 }
2998 }
2999}
3000
3001fn compute_scroll_position(
3002 snapshot: &DisplayMapSnapshot,
3003 mut scroll_position: Vector2F,
3004 scroll_top_anchor: &Anchor,
3005) -> Vector2F {
3006 let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
3007 scroll_position.set_y(scroll_top + scroll_position.y());
3008 scroll_position
3009}
3010
3011pub enum Event {
3012 Activate,
3013 Edited,
3014 Blurred,
3015 Dirtied,
3016 Saved,
3017 FileHandleChanged,
3018 Closed,
3019}
3020
3021impl Entity for Editor {
3022 type Event = Event;
3023
3024 fn release(&mut self, cx: &mut MutableAppContext) {
3025 self.buffer.update(cx, |buffer, cx| {
3026 buffer
3027 .remove_selection_set(self.selection_set_id, cx)
3028 .unwrap();
3029 });
3030 }
3031}
3032
3033impl View for Editor {
3034 fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
3035 let settings = self.build_settings.borrow_mut()(cx);
3036 self.display_map.update(cx, |map, cx| {
3037 map.set_font(
3038 settings.style.text.font_id,
3039 settings.style.text.font_size,
3040 cx,
3041 )
3042 });
3043 EditorElement::new(self.handle.clone(), settings).boxed()
3044 }
3045
3046 fn ui_name() -> &'static str {
3047 "Editor"
3048 }
3049
3050 fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
3051 self.focused = true;
3052 self.blink_cursors(self.blink_epoch, cx);
3053 self.buffer.update(cx, |buffer, cx| {
3054 buffer
3055 .set_active_selection_set(Some(self.selection_set_id), cx)
3056 .unwrap();
3057 });
3058 }
3059
3060 fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
3061 self.focused = false;
3062 self.show_local_cursors = false;
3063 self.buffer.update(cx, |buffer, cx| {
3064 buffer.set_active_selection_set(None, cx).unwrap();
3065 });
3066 cx.emit(Event::Blurred);
3067 cx.notify();
3068 }
3069
3070 fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
3071 let mut cx = Self::default_keymap_context();
3072 let mode = match self.mode {
3073 EditorMode::SingleLine => "single_line",
3074 EditorMode::AutoHeight { .. } => "auto_height",
3075 EditorMode::Full => "full",
3076 };
3077 cx.map.insert("mode".into(), mode.into());
3078 cx
3079 }
3080}
3081
3082impl SelectionExt for Selection<Point> {
3083 fn display_range(&self, map: &DisplayMapSnapshot) -> Range<DisplayPoint> {
3084 let start = self.start.to_display_point(map);
3085 let end = self.end.to_display_point(map);
3086 if self.reversed {
3087 end..start
3088 } else {
3089 start..end
3090 }
3091 }
3092
3093 fn spanned_rows(
3094 &self,
3095 include_end_if_at_line_start: bool,
3096 map: &DisplayMapSnapshot,
3097 ) -> SpannedRows {
3098 let display_start = self.start.to_display_point(map);
3099 let mut display_end = self.end.to_display_point(map);
3100 if !include_end_if_at_line_start
3101 && display_end.row() != map.max_point().row()
3102 && display_start.row() != display_end.row()
3103 && display_end.column() == 0
3104 {
3105 *display_end.row_mut() -= 1;
3106 }
3107
3108 let (display_start, buffer_start) = map.prev_row_boundary(display_start);
3109 let (display_end, buffer_end) = map.next_row_boundary(display_end);
3110
3111 SpannedRows {
3112 buffer_rows: buffer_start.row..buffer_end.row + 1,
3113 display_rows: display_start.row()..display_end.row() + 1,
3114 }
3115 }
3116}
3117
3118pub fn diagnostic_style(
3119 severity: DiagnosticSeverity,
3120 valid: bool,
3121 style: &EditorStyle,
3122) -> DiagnosticStyle {
3123 match (severity, valid) {
3124 (DiagnosticSeverity::ERROR, true) => style.error_diagnostic,
3125 (DiagnosticSeverity::ERROR, false) => style.invalid_error_diagnostic,
3126 (DiagnosticSeverity::WARNING, true) => style.warning_diagnostic,
3127 (DiagnosticSeverity::WARNING, false) => style.invalid_warning_diagnostic,
3128 (DiagnosticSeverity::INFORMATION, true) => style.information_diagnostic,
3129 (DiagnosticSeverity::INFORMATION, false) => style.invalid_information_diagnostic,
3130 (DiagnosticSeverity::HINT, true) => style.hint_diagnostic,
3131 (DiagnosticSeverity::HINT, false) => style.invalid_hint_diagnostic,
3132 _ => Default::default(),
3133 }
3134}
3135
3136#[cfg(test)]
3137mod tests {
3138 use super::*;
3139 use crate::test::sample_text;
3140 use buffer::Point;
3141 use unindent::Unindent;
3142
3143 #[gpui::test]
3144 fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
3145 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
3146 let settings = EditorSettings::test(cx);
3147 let (_, editor) =
3148 cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3149
3150 editor.update(cx, |view, cx| {
3151 view.begin_selection(DisplayPoint::new(2, 2), false, cx);
3152 });
3153
3154 assert_eq!(
3155 editor.update(cx, |view, cx| view.selection_ranges(cx)),
3156 [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
3157 );
3158
3159 editor.update(cx, |view, cx| {
3160 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
3161 });
3162
3163 assert_eq!(
3164 editor.update(cx, |view, cx| view.selection_ranges(cx)),
3165 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3166 );
3167
3168 editor.update(cx, |view, cx| {
3169 view.update_selection(DisplayPoint::new(1, 1), 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(1, 1)]
3175 );
3176
3177 editor.update(cx, |view, cx| {
3178 view.end_selection(cx);
3179 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
3180 });
3181
3182 assert_eq!(
3183 editor.update(cx, |view, cx| view.selection_ranges(cx)),
3184 [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
3185 );
3186
3187 editor.update(cx, |view, cx| {
3188 view.begin_selection(DisplayPoint::new(3, 3), true, cx);
3189 view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), cx);
3190 });
3191
3192 assert_eq!(
3193 editor.update(cx, |view, cx| view.selection_ranges(cx)),
3194 [
3195 DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
3196 DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
3197 ]
3198 );
3199
3200 editor.update(cx, |view, cx| {
3201 view.end_selection(cx);
3202 });
3203
3204 assert_eq!(
3205 editor.update(cx, |view, cx| view.selection_ranges(cx)),
3206 [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
3207 );
3208 }
3209
3210 #[gpui::test]
3211 fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
3212 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
3213 let settings = EditorSettings::test(cx);
3214 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3215
3216 view.update(cx, |view, cx| {
3217 view.begin_selection(DisplayPoint::new(2, 2), false, cx);
3218 assert_eq!(
3219 view.selection_ranges(cx),
3220 [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
3221 );
3222 });
3223
3224 view.update(cx, |view, cx| {
3225 view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), cx);
3226 assert_eq!(
3227 view.selection_ranges(cx),
3228 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3229 );
3230 });
3231
3232 view.update(cx, |view, cx| {
3233 view.cancel(&Cancel, cx);
3234 view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
3235 assert_eq!(
3236 view.selection_ranges(cx),
3237 [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3238 );
3239 });
3240 }
3241
3242 #[gpui::test]
3243 fn test_cancel(cx: &mut gpui::MutableAppContext) {
3244 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx));
3245 let settings = EditorSettings::test(cx);
3246 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3247
3248 view.update(cx, |view, cx| {
3249 view.begin_selection(DisplayPoint::new(3, 4), false, cx);
3250 view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
3251 view.end_selection(cx);
3252
3253 view.begin_selection(DisplayPoint::new(0, 1), true, cx);
3254 view.update_selection(DisplayPoint::new(0, 3), Vector2F::zero(), cx);
3255 view.end_selection(cx);
3256 assert_eq!(
3257 view.selection_ranges(cx),
3258 [
3259 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3260 DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
3261 ]
3262 );
3263 });
3264
3265 view.update(cx, |view, cx| {
3266 view.cancel(&Cancel, cx);
3267 assert_eq!(
3268 view.selection_ranges(cx),
3269 [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
3270 );
3271 });
3272
3273 view.update(cx, |view, cx| {
3274 view.cancel(&Cancel, cx);
3275 assert_eq!(
3276 view.selection_ranges(cx),
3277 [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
3278 );
3279 });
3280 }
3281
3282 #[gpui::test]
3283 fn test_fold(cx: &mut gpui::MutableAppContext) {
3284 let buffer = cx.add_model(|cx| {
3285 Buffer::new(
3286 0,
3287 "
3288 impl Foo {
3289 // Hello!
3290
3291 fn a() {
3292 1
3293 }
3294
3295 fn b() {
3296 2
3297 }
3298
3299 fn c() {
3300 3
3301 }
3302 }
3303 "
3304 .unindent(),
3305 cx,
3306 )
3307 });
3308 let settings = EditorSettings::test(&cx);
3309 let (_, view) = cx.add_window(Default::default(), |cx| {
3310 build_editor(buffer.clone(), settings, cx)
3311 });
3312
3313 view.update(cx, |view, cx| {
3314 view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx)
3315 .unwrap();
3316 view.fold(&Fold, cx);
3317 assert_eq!(
3318 view.display_text(cx),
3319 "
3320 impl Foo {
3321 // Hello!
3322
3323 fn a() {
3324 1
3325 }
3326
3327 fn b() {…
3328 }
3329
3330 fn c() {…
3331 }
3332 }
3333 "
3334 .unindent(),
3335 );
3336
3337 view.fold(&Fold, cx);
3338 assert_eq!(
3339 view.display_text(cx),
3340 "
3341 impl Foo {…
3342 }
3343 "
3344 .unindent(),
3345 );
3346
3347 view.unfold(&Unfold, cx);
3348 assert_eq!(
3349 view.display_text(cx),
3350 "
3351 impl Foo {
3352 // Hello!
3353
3354 fn a() {
3355 1
3356 }
3357
3358 fn b() {…
3359 }
3360
3361 fn c() {…
3362 }
3363 }
3364 "
3365 .unindent(),
3366 );
3367
3368 view.unfold(&Unfold, cx);
3369 assert_eq!(view.display_text(cx), buffer.read(cx).text());
3370 });
3371 }
3372
3373 #[gpui::test]
3374 fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
3375 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6), cx));
3376 let settings = EditorSettings::test(&cx);
3377 let (_, view) = cx.add_window(Default::default(), |cx| {
3378 build_editor(buffer.clone(), settings, cx)
3379 });
3380
3381 buffer.update(cx, |buffer, cx| {
3382 buffer.edit(
3383 vec![
3384 Point::new(1, 0)..Point::new(1, 0),
3385 Point::new(1, 1)..Point::new(1, 1),
3386 ],
3387 "\t",
3388 cx,
3389 );
3390 });
3391
3392 view.update(cx, |view, cx| {
3393 assert_eq!(
3394 view.selection_ranges(cx),
3395 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3396 );
3397
3398 view.move_down(&MoveDown, cx);
3399 assert_eq!(
3400 view.selection_ranges(cx),
3401 &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3402 );
3403
3404 view.move_right(&MoveRight, cx);
3405 assert_eq!(
3406 view.selection_ranges(cx),
3407 &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
3408 );
3409
3410 view.move_left(&MoveLeft, cx);
3411 assert_eq!(
3412 view.selection_ranges(cx),
3413 &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3414 );
3415
3416 view.move_up(&MoveUp, cx);
3417 assert_eq!(
3418 view.selection_ranges(cx),
3419 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3420 );
3421
3422 view.move_to_end(&MoveToEnd, cx);
3423 assert_eq!(
3424 view.selection_ranges(cx),
3425 &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
3426 );
3427
3428 view.move_to_beginning(&MoveToBeginning, cx);
3429 assert_eq!(
3430 view.selection_ranges(cx),
3431 &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3432 );
3433
3434 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx)
3435 .unwrap();
3436 view.select_to_beginning(&SelectToBeginning, cx);
3437 assert_eq!(
3438 view.selection_ranges(cx),
3439 &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
3440 );
3441
3442 view.select_to_end(&SelectToEnd, cx);
3443 assert_eq!(
3444 view.selection_ranges(cx),
3445 &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
3446 );
3447 });
3448 }
3449
3450 #[gpui::test]
3451 fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
3452 let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx));
3453 let settings = EditorSettings::test(&cx);
3454 let (_, view) = cx.add_window(Default::default(), |cx| {
3455 build_editor(buffer.clone(), settings, cx)
3456 });
3457
3458 assert_eq!('ⓐ'.len_utf8(), 3);
3459 assert_eq!('α'.len_utf8(), 2);
3460
3461 view.update(cx, |view, cx| {
3462 view.fold_ranges(
3463 vec![
3464 Point::new(0, 6)..Point::new(0, 12),
3465 Point::new(1, 2)..Point::new(1, 4),
3466 Point::new(2, 4)..Point::new(2, 8),
3467 ],
3468 cx,
3469 );
3470 assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
3471
3472 view.move_right(&MoveRight, cx);
3473 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐ".len())]);
3474 view.move_right(&MoveRight, cx);
3475 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
3476 view.move_right(&MoveRight, cx);
3477 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
3478
3479 view.move_down(&MoveDown, cx);
3480 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…".len())]);
3481 view.move_left(&MoveLeft, cx);
3482 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab".len())]);
3483 view.move_left(&MoveLeft, cx);
3484 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "a".len())]);
3485
3486 view.move_down(&MoveDown, cx);
3487 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "α".len())]);
3488 view.move_right(&MoveRight, cx);
3489 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ".len())]);
3490 view.move_right(&MoveRight, cx);
3491 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…".len())]);
3492 view.move_right(&MoveRight, cx);
3493 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…ε".len())]);
3494
3495 view.move_up(&MoveUp, cx);
3496 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…e".len())]);
3497 view.move_up(&MoveUp, cx);
3498 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…ⓔ".len())]);
3499 view.move_left(&MoveLeft, cx);
3500 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
3501 view.move_left(&MoveLeft, cx);
3502 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
3503 view.move_left(&MoveLeft, cx);
3504 assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐ".len())]);
3505 });
3506 }
3507
3508 #[gpui::test]
3509 fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
3510 let buffer = cx.add_model(|cx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx));
3511 let settings = EditorSettings::test(&cx);
3512 let (_, view) = cx.add_window(Default::default(), |cx| {
3513 build_editor(buffer.clone(), settings, cx)
3514 });
3515 view.update(cx, |view, cx| {
3516 view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx)
3517 .unwrap();
3518
3519 view.move_down(&MoveDown, cx);
3520 assert_eq!(view.selection_ranges(cx), &[empty_range(1, "abcd".len())]);
3521
3522 view.move_down(&MoveDown, cx);
3523 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
3524
3525 view.move_down(&MoveDown, cx);
3526 assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
3527
3528 view.move_down(&MoveDown, cx);
3529 assert_eq!(view.selection_ranges(cx), &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]);
3530
3531 view.move_up(&MoveUp, cx);
3532 assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
3533
3534 view.move_up(&MoveUp, cx);
3535 assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
3536 });
3537 }
3538
3539 #[gpui::test]
3540 fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
3541 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\n def", cx));
3542 let settings = EditorSettings::test(&cx);
3543 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3544 view.update(cx, |view, cx| {
3545 view.select_display_ranges(
3546 &[
3547 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3548 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
3549 ],
3550 cx,
3551 )
3552 .unwrap();
3553 });
3554
3555 view.update(cx, |view, cx| {
3556 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3557 assert_eq!(
3558 view.selection_ranges(cx),
3559 &[
3560 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3561 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3562 ]
3563 );
3564 });
3565
3566 view.update(cx, |view, cx| {
3567 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3568 assert_eq!(
3569 view.selection_ranges(cx),
3570 &[
3571 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3572 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3573 ]
3574 );
3575 });
3576
3577 view.update(cx, |view, cx| {
3578 view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
3579 assert_eq!(
3580 view.selection_ranges(cx),
3581 &[
3582 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3583 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3584 ]
3585 );
3586 });
3587
3588 view.update(cx, |view, cx| {
3589 view.move_to_end_of_line(&MoveToEndOfLine, cx);
3590 assert_eq!(
3591 view.selection_ranges(cx),
3592 &[
3593 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3594 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3595 ]
3596 );
3597 });
3598
3599 // Moving to the end of line again is a no-op.
3600 view.update(cx, |view, cx| {
3601 view.move_to_end_of_line(&MoveToEndOfLine, cx);
3602 assert_eq!(
3603 view.selection_ranges(cx),
3604 &[
3605 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3606 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3607 ]
3608 );
3609 });
3610
3611 view.update(cx, |view, cx| {
3612 view.move_left(&MoveLeft, cx);
3613 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3614 assert_eq!(
3615 view.selection_ranges(cx),
3616 &[
3617 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3618 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
3619 ]
3620 );
3621 });
3622
3623 view.update(cx, |view, cx| {
3624 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3625 assert_eq!(
3626 view.selection_ranges(cx),
3627 &[
3628 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3629 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
3630 ]
3631 );
3632 });
3633
3634 view.update(cx, |view, cx| {
3635 view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
3636 assert_eq!(
3637 view.selection_ranges(cx),
3638 &[
3639 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
3640 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
3641 ]
3642 );
3643 });
3644
3645 view.update(cx, |view, cx| {
3646 view.select_to_end_of_line(&SelectToEndOfLine, cx);
3647 assert_eq!(
3648 view.selection_ranges(cx),
3649 &[
3650 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
3651 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
3652 ]
3653 );
3654 });
3655
3656 view.update(cx, |view, cx| {
3657 view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
3658 assert_eq!(view.display_text(cx), "ab\n de");
3659 assert_eq!(
3660 view.selection_ranges(cx),
3661 &[
3662 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3663 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
3664 ]
3665 );
3666 });
3667
3668 view.update(cx, |view, cx| {
3669 view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
3670 assert_eq!(view.display_text(cx), "\n");
3671 assert_eq!(
3672 view.selection_ranges(cx),
3673 &[
3674 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3675 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3676 ]
3677 );
3678 });
3679 }
3680
3681 #[gpui::test]
3682 fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
3683 let buffer =
3684 cx.add_model(|cx| Buffer::new(0, "use std::str::{foo, bar}\n\n {baz.qux()}", cx));
3685 let settings = EditorSettings::test(&cx);
3686 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3687 view.update(cx, |view, cx| {
3688 view.select_display_ranges(
3689 &[
3690 DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
3691 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
3692 ],
3693 cx,
3694 )
3695 .unwrap();
3696 });
3697
3698 view.update(cx, |view, cx| {
3699 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3700 assert_eq!(
3701 view.selection_ranges(cx),
3702 &[
3703 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3704 DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3705 ]
3706 );
3707 });
3708
3709 view.update(cx, |view, cx| {
3710 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3711 assert_eq!(
3712 view.selection_ranges(cx),
3713 &[
3714 DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3715 DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
3716 ]
3717 );
3718 });
3719
3720 view.update(cx, |view, cx| {
3721 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3722 assert_eq!(
3723 view.selection_ranges(cx),
3724 &[
3725 DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
3726 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
3727 ]
3728 );
3729 });
3730
3731 view.update(cx, |view, cx| {
3732 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3733 assert_eq!(
3734 view.selection_ranges(cx),
3735 &[
3736 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3737 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3738 ]
3739 );
3740 });
3741
3742 view.update(cx, |view, cx| {
3743 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3744 assert_eq!(
3745 view.selection_ranges(cx),
3746 &[
3747 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3748 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 23),
3749 ]
3750 );
3751 });
3752
3753 view.update(cx, |view, cx| {
3754 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3755 assert_eq!(
3756 view.selection_ranges(cx),
3757 &[
3758 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3759 DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
3760 ]
3761 );
3762 });
3763
3764 view.update(cx, |view, cx| {
3765 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3766 assert_eq!(
3767 view.selection_ranges(cx),
3768 &[
3769 DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3770 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3771 ]
3772 );
3773 });
3774
3775 view.update(cx, |view, cx| {
3776 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3777 assert_eq!(
3778 view.selection_ranges(cx),
3779 &[
3780 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3781 DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3782 ]
3783 );
3784 });
3785
3786 view.update(cx, |view, cx| {
3787 view.move_right(&MoveRight, cx);
3788 view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
3789 assert_eq!(
3790 view.selection_ranges(cx),
3791 &[
3792 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3793 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
3794 ]
3795 );
3796 });
3797
3798 view.update(cx, |view, cx| {
3799 view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
3800 assert_eq!(
3801 view.selection_ranges(cx),
3802 &[
3803 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 7),
3804 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 2),
3805 ]
3806 );
3807 });
3808
3809 view.update(cx, |view, cx| {
3810 view.select_to_next_word_boundary(&SelectToNextWordBoundary, cx);
3811 assert_eq!(
3812 view.selection_ranges(cx),
3813 &[
3814 DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3815 DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
3816 ]
3817 );
3818 });
3819 }
3820
3821 #[gpui::test]
3822 fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
3823 let buffer =
3824 cx.add_model(|cx| Buffer::new(0, "use one::{\n two::three::four::five\n};", cx));
3825 let settings = EditorSettings::test(&cx);
3826 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3827
3828 view.update(cx, |view, cx| {
3829 view.set_wrap_width(140., cx);
3830 assert_eq!(
3831 view.display_text(cx),
3832 "use one::{\n two::three::\n four::five\n};"
3833 );
3834
3835 view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx)
3836 .unwrap();
3837
3838 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3839 assert_eq!(
3840 view.selection_ranges(cx),
3841 &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
3842 );
3843
3844 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3845 assert_eq!(
3846 view.selection_ranges(cx),
3847 &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
3848 );
3849
3850 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3851 assert_eq!(
3852 view.selection_ranges(cx),
3853 &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
3854 );
3855
3856 view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
3857 assert_eq!(
3858 view.selection_ranges(cx),
3859 &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
3860 );
3861
3862 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3863 assert_eq!(
3864 view.selection_ranges(cx),
3865 &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
3866 );
3867
3868 view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
3869 assert_eq!(
3870 view.selection_ranges(cx),
3871 &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
3872 );
3873 });
3874 }
3875
3876 #[gpui::test]
3877 fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
3878 let buffer = cx.add_model(|cx| Buffer::new(0, "one two three four", cx));
3879 let settings = EditorSettings::test(&cx);
3880 let (_, view) = cx.add_window(Default::default(), |cx| {
3881 build_editor(buffer.clone(), settings, cx)
3882 });
3883
3884 view.update(cx, |view, cx| {
3885 view.select_display_ranges(
3886 &[
3887 // an empty selection - the preceding word fragment is deleted
3888 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3889 // characters selected - they are deleted
3890 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
3891 ],
3892 cx,
3893 )
3894 .unwrap();
3895 view.delete_to_previous_word_boundary(&DeleteToPreviousWordBoundary, cx);
3896 });
3897
3898 assert_eq!(buffer.read(cx).text(), "e two te four");
3899
3900 view.update(cx, |view, cx| {
3901 view.select_display_ranges(
3902 &[
3903 // an empty selection - the following word fragment is deleted
3904 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3905 // characters selected - they are deleted
3906 DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
3907 ],
3908 cx,
3909 )
3910 .unwrap();
3911 view.delete_to_next_word_boundary(&DeleteToNextWordBoundary, cx);
3912 });
3913
3914 assert_eq!(buffer.read(cx).text(), "e t te our");
3915 }
3916
3917 #[gpui::test]
3918 fn test_newline(cx: &mut gpui::MutableAppContext) {
3919 let buffer = cx.add_model(|cx| Buffer::new(0, "aaaa\n bbbb\n", cx));
3920 let settings = EditorSettings::test(&cx);
3921 let (_, view) = cx.add_window(Default::default(), |cx| {
3922 build_editor(buffer.clone(), settings, cx)
3923 });
3924
3925 view.update(cx, |view, cx| {
3926 view.select_display_ranges(
3927 &[
3928 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3929 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3930 DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
3931 ],
3932 cx,
3933 )
3934 .unwrap();
3935
3936 view.newline(&Newline, cx);
3937 assert_eq!(view.text(cx), "aa\naa\n \n bb\n bb\n");
3938 });
3939 }
3940
3941 #[gpui::test]
3942 fn test_backspace(cx: &mut gpui::MutableAppContext) {
3943 let buffer = cx.add_model(|cx| {
3944 Buffer::new(
3945 0,
3946 "one two three\nfour five six\nseven eight nine\nten\n",
3947 cx,
3948 )
3949 });
3950 let settings = EditorSettings::test(&cx);
3951 let (_, view) = cx.add_window(Default::default(), |cx| {
3952 build_editor(buffer.clone(), settings, cx)
3953 });
3954
3955 view.update(cx, |view, cx| {
3956 view.select_display_ranges(
3957 &[
3958 // an empty selection - the preceding character is deleted
3959 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3960 // one character selected - it is deleted
3961 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3962 // a line suffix selected - it is deleted
3963 DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
3964 ],
3965 cx,
3966 )
3967 .unwrap();
3968 view.backspace(&Backspace, cx);
3969 });
3970
3971 assert_eq!(
3972 buffer.read(cx).text(),
3973 "oe two three\nfou five six\nseven ten\n"
3974 );
3975 }
3976
3977 #[gpui::test]
3978 fn test_delete(cx: &mut gpui::MutableAppContext) {
3979 let buffer = cx.add_model(|cx| {
3980 Buffer::new(
3981 0,
3982 "one two three\nfour five six\nseven eight nine\nten\n",
3983 cx,
3984 )
3985 });
3986 let settings = EditorSettings::test(&cx);
3987 let (_, view) = cx.add_window(Default::default(), |cx| {
3988 build_editor(buffer.clone(), settings, cx)
3989 });
3990
3991 view.update(cx, |view, cx| {
3992 view.select_display_ranges(
3993 &[
3994 // an empty selection - the following character is deleted
3995 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3996 // one character selected - it is deleted
3997 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3998 // a line suffix selected - it is deleted
3999 DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
4000 ],
4001 cx,
4002 )
4003 .unwrap();
4004 view.delete(&Delete, cx);
4005 });
4006
4007 assert_eq!(
4008 buffer.read(cx).text(),
4009 "on two three\nfou five six\nseven ten\n"
4010 );
4011 }
4012
4013 #[gpui::test]
4014 fn test_delete_line(cx: &mut gpui::MutableAppContext) {
4015 let settings = EditorSettings::test(&cx);
4016 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
4017 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4018 view.update(cx, |view, cx| {
4019 view.select_display_ranges(
4020 &[
4021 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4022 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4023 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4024 ],
4025 cx,
4026 )
4027 .unwrap();
4028 view.delete_line(&DeleteLine, cx);
4029 assert_eq!(view.display_text(cx), "ghi");
4030 assert_eq!(
4031 view.selection_ranges(cx),
4032 vec![
4033 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4034 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
4035 ]
4036 );
4037 });
4038
4039 let settings = EditorSettings::test(&cx);
4040 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
4041 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4042 view.update(cx, |view, cx| {
4043 view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx)
4044 .unwrap();
4045 view.delete_line(&DeleteLine, cx);
4046 assert_eq!(view.display_text(cx), "ghi\n");
4047 assert_eq!(
4048 view.selection_ranges(cx),
4049 vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
4050 );
4051 });
4052 }
4053
4054 #[gpui::test]
4055 fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
4056 let settings = EditorSettings::test(&cx);
4057 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
4058 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4059 view.update(cx, |view, cx| {
4060 view.select_display_ranges(
4061 &[
4062 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4063 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4064 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4065 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4066 ],
4067 cx,
4068 )
4069 .unwrap();
4070 view.duplicate_line(&DuplicateLine, cx);
4071 assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
4072 assert_eq!(
4073 view.selection_ranges(cx),
4074 vec![
4075 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4076 DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
4077 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4078 DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
4079 ]
4080 );
4081 });
4082
4083 let settings = EditorSettings::test(&cx);
4084 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndef\nghi\n", cx));
4085 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4086 view.update(cx, |view, cx| {
4087 view.select_display_ranges(
4088 &[
4089 DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
4090 DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
4091 ],
4092 cx,
4093 )
4094 .unwrap();
4095 view.duplicate_line(&DuplicateLine, cx);
4096 assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
4097 assert_eq!(
4098 view.selection_ranges(cx),
4099 vec![
4100 DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
4101 DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
4102 ]
4103 );
4104 });
4105 }
4106
4107 #[gpui::test]
4108 fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
4109 let settings = EditorSettings::test(&cx);
4110 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(10, 5), cx));
4111 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4112 view.update(cx, |view, cx| {
4113 view.fold_ranges(
4114 vec![
4115 Point::new(0, 2)..Point::new(1, 2),
4116 Point::new(2, 3)..Point::new(4, 1),
4117 Point::new(7, 0)..Point::new(8, 4),
4118 ],
4119 cx,
4120 );
4121 view.select_display_ranges(
4122 &[
4123 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4124 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4125 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4126 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
4127 ],
4128 cx,
4129 )
4130 .unwrap();
4131 assert_eq!(
4132 view.display_text(cx),
4133 "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
4134 );
4135
4136 view.move_line_up(&MoveLineUp, cx);
4137 assert_eq!(
4138 view.display_text(cx),
4139 "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
4140 );
4141 assert_eq!(
4142 view.selection_ranges(cx),
4143 vec![
4144 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4145 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4146 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
4147 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
4148 ]
4149 );
4150 });
4151
4152 view.update(cx, |view, cx| {
4153 view.move_line_down(&MoveLineDown, cx);
4154 assert_eq!(
4155 view.display_text(cx),
4156 "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
4157 );
4158 assert_eq!(
4159 view.selection_ranges(cx),
4160 vec![
4161 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4162 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4163 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4164 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
4165 ]
4166 );
4167 });
4168
4169 view.update(cx, |view, cx| {
4170 view.move_line_down(&MoveLineDown, cx);
4171 assert_eq!(
4172 view.display_text(cx),
4173 "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
4174 );
4175 assert_eq!(
4176 view.selection_ranges(cx),
4177 vec![
4178 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4179 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4180 DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4181 DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
4182 ]
4183 );
4184 });
4185
4186 view.update(cx, |view, cx| {
4187 view.move_line_up(&MoveLineUp, cx);
4188 assert_eq!(
4189 view.display_text(cx),
4190 "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
4191 );
4192 assert_eq!(
4193 view.selection_ranges(cx),
4194 vec![
4195 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4196 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4197 DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
4198 DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
4199 ]
4200 );
4201 });
4202 }
4203
4204 #[gpui::test]
4205 fn test_clipboard(cx: &mut gpui::MutableAppContext) {
4206 let buffer = cx.add_model(|cx| Buffer::new(0, "one✅ two three four five six ", cx));
4207 let settings = EditorSettings::test(&cx);
4208 let view = cx
4209 .add_window(Default::default(), |cx| {
4210 build_editor(buffer.clone(), settings, cx)
4211 })
4212 .1;
4213
4214 // Cut with three selections. Clipboard text is divided into three slices.
4215 view.update(cx, |view, cx| {
4216 view.select_ranges(vec![0..7, 11..17, 22..27], false, cx);
4217 view.cut(&Cut, cx);
4218 assert_eq!(view.display_text(cx), "two four six ");
4219 });
4220
4221 // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
4222 view.update(cx, |view, cx| {
4223 view.select_ranges(vec![4..4, 9..9, 13..13], false, cx);
4224 view.paste(&Paste, cx);
4225 assert_eq!(view.display_text(cx), "two one✅ four three six five ");
4226 assert_eq!(
4227 view.selection_ranges(cx),
4228 &[
4229 DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
4230 DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
4231 DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
4232 ]
4233 );
4234 });
4235
4236 // Paste again but with only two cursors. Since the number of cursors doesn't
4237 // match the number of slices in the clipboard, the entire clipboard text
4238 // is pasted at each cursor.
4239 view.update(cx, |view, cx| {
4240 view.select_ranges(vec![0..0, 31..31], false, cx);
4241 view.handle_input(&Input("( ".into()), cx);
4242 view.paste(&Paste, cx);
4243 view.handle_input(&Input(") ".into()), cx);
4244 assert_eq!(
4245 view.display_text(cx),
4246 "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4247 );
4248 });
4249
4250 view.update(cx, |view, cx| {
4251 view.select_ranges(vec![0..0], false, cx);
4252 view.handle_input(&Input("123\n4567\n89\n".into()), cx);
4253 assert_eq!(
4254 view.display_text(cx),
4255 "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4256 );
4257 });
4258
4259 // Cut with three selections, one of which is full-line.
4260 view.update(cx, |view, cx| {
4261 view.select_display_ranges(
4262 &[
4263 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
4264 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4265 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
4266 ],
4267 cx,
4268 )
4269 .unwrap();
4270 view.cut(&Cut, cx);
4271 assert_eq!(
4272 view.display_text(cx),
4273 "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4274 );
4275 });
4276
4277 // Paste with three selections, noticing how the copied selection that was full-line
4278 // gets inserted before the second cursor.
4279 view.update(cx, |view, cx| {
4280 view.select_display_ranges(
4281 &[
4282 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4283 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4284 DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
4285 ],
4286 cx,
4287 )
4288 .unwrap();
4289 view.paste(&Paste, cx);
4290 assert_eq!(
4291 view.display_text(cx),
4292 "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
4293 );
4294 assert_eq!(
4295 view.selection_ranges(cx),
4296 &[
4297 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4298 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4299 DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
4300 ]
4301 );
4302 });
4303
4304 // Copy with a single cursor only, which writes the whole line into the clipboard.
4305 view.update(cx, |view, cx| {
4306 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx)
4307 .unwrap();
4308 view.copy(&Copy, cx);
4309 });
4310
4311 // Paste with three selections, noticing how the copied full-line selection is inserted
4312 // before the empty selections but replaces the selection that is non-empty.
4313 view.update(cx, |view, cx| {
4314 view.select_display_ranges(
4315 &[
4316 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4317 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
4318 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4319 ],
4320 cx,
4321 )
4322 .unwrap();
4323 view.paste(&Paste, cx);
4324 assert_eq!(
4325 view.display_text(cx),
4326 "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
4327 );
4328 assert_eq!(
4329 view.selection_ranges(cx),
4330 &[
4331 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4332 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4333 DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
4334 ]
4335 );
4336 });
4337 }
4338
4339 #[gpui::test]
4340 fn test_select_all(cx: &mut gpui::MutableAppContext) {
4341 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\nde\nfgh", cx));
4342 let settings = EditorSettings::test(&cx);
4343 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4344 view.update(cx, |view, cx| {
4345 view.select_all(&SelectAll, cx);
4346 assert_eq!(
4347 view.selection_ranges(cx),
4348 &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
4349 );
4350 });
4351 }
4352
4353 #[gpui::test]
4354 fn test_select_line(cx: &mut gpui::MutableAppContext) {
4355 let settings = EditorSettings::test(&cx);
4356 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 5), cx));
4357 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4358 view.update(cx, |view, cx| {
4359 view.select_display_ranges(
4360 &[
4361 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4362 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4363 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4364 DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
4365 ],
4366 cx,
4367 )
4368 .unwrap();
4369 view.select_line(&SelectLine, cx);
4370 assert_eq!(
4371 view.selection_ranges(cx),
4372 vec![
4373 DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
4374 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
4375 ]
4376 );
4377 });
4378
4379 view.update(cx, |view, cx| {
4380 view.select_line(&SelectLine, cx);
4381 assert_eq!(
4382 view.selection_ranges(cx),
4383 vec![
4384 DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
4385 DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
4386 ]
4387 );
4388 });
4389
4390 view.update(cx, |view, cx| {
4391 view.select_line(&SelectLine, cx);
4392 assert_eq!(
4393 view.selection_ranges(cx),
4394 vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
4395 );
4396 });
4397 }
4398
4399 #[gpui::test]
4400 fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
4401 let settings = EditorSettings::test(&cx);
4402 let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(9, 5), cx));
4403 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4404 view.update(cx, |view, cx| {
4405 view.fold_ranges(
4406 vec![
4407 Point::new(0, 2)..Point::new(1, 2),
4408 Point::new(2, 3)..Point::new(4, 1),
4409 Point::new(7, 0)..Point::new(8, 4),
4410 ],
4411 cx,
4412 );
4413 view.select_display_ranges(
4414 &[
4415 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4416 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4417 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4418 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
4419 ],
4420 cx,
4421 )
4422 .unwrap();
4423 assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
4424 });
4425
4426 view.update(cx, |view, cx| {
4427 view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
4428 assert_eq!(
4429 view.display_text(cx),
4430 "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
4431 );
4432 assert_eq!(
4433 view.selection_ranges(cx),
4434 [
4435 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4436 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4437 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
4438 DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
4439 ]
4440 );
4441 });
4442
4443 view.update(cx, |view, cx| {
4444 view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx)
4445 .unwrap();
4446 view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
4447 assert_eq!(
4448 view.display_text(cx),
4449 "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
4450 );
4451 assert_eq!(
4452 view.selection_ranges(cx),
4453 [
4454 DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
4455 DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
4456 DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
4457 DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
4458 DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
4459 DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
4460 DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
4461 DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
4462 ]
4463 );
4464 });
4465 }
4466
4467 #[gpui::test]
4468 fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
4469 let settings = EditorSettings::test(&cx);
4470 let buffer = cx.add_model(|cx| Buffer::new(0, "abc\ndefghi\n\njk\nlmno\n", cx));
4471 let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4472
4473 view.update(cx, |view, cx| {
4474 view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx)
4475 .unwrap();
4476 });
4477 view.update(cx, |view, cx| {
4478 view.add_selection_above(&AddSelectionAbove, cx);
4479 assert_eq!(
4480 view.selection_ranges(cx),
4481 vec![
4482 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4483 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
4484 ]
4485 );
4486 });
4487
4488 view.update(cx, |view, cx| {
4489 view.add_selection_above(&AddSelectionAbove, cx);
4490 assert_eq!(
4491 view.selection_ranges(cx),
4492 vec![
4493 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4494 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
4495 ]
4496 );
4497 });
4498
4499 view.update(cx, |view, cx| {
4500 view.add_selection_below(&AddSelectionBelow, cx);
4501 assert_eq!(
4502 view.selection_ranges(cx),
4503 vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
4504 );
4505 });
4506
4507 view.update(cx, |view, cx| {
4508 view.add_selection_below(&AddSelectionBelow, cx);
4509 assert_eq!(
4510 view.selection_ranges(cx),
4511 vec![
4512 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
4513 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
4514 ]
4515 );
4516 });
4517
4518 view.update(cx, |view, cx| {
4519 view.add_selection_below(&AddSelectionBelow, cx);
4520 assert_eq!(
4521 view.selection_ranges(cx),
4522 vec![
4523 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
4524 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
4525 ]
4526 );
4527 });
4528
4529 view.update(cx, |view, cx| {
4530 view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx)
4531 .unwrap();
4532 });
4533 view.update(cx, |view, cx| {
4534 view.add_selection_below(&AddSelectionBelow, cx);
4535 assert_eq!(
4536 view.selection_ranges(cx),
4537 vec![
4538 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4539 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
4540 ]
4541 );
4542 });
4543
4544 view.update(cx, |view, cx| {
4545 view.add_selection_below(&AddSelectionBelow, cx);
4546 assert_eq!(
4547 view.selection_ranges(cx),
4548 vec![
4549 DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4550 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
4551 ]
4552 );
4553 });
4554
4555 view.update(cx, |view, cx| {
4556 view.add_selection_above(&AddSelectionAbove, cx);
4557 assert_eq!(
4558 view.selection_ranges(cx),
4559 vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
4560 );
4561 });
4562
4563 view.update(cx, |view, cx| {
4564 view.add_selection_above(&AddSelectionAbove, cx);
4565 assert_eq!(
4566 view.selection_ranges(cx),
4567 vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
4568 );
4569 });
4570
4571 view.update(cx, |view, cx| {
4572 view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx)
4573 .unwrap();
4574 view.add_selection_below(&AddSelectionBelow, cx);
4575 assert_eq!(
4576 view.selection_ranges(cx),
4577 vec![
4578 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4579 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4580 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4581 ]
4582 );
4583 });
4584
4585 view.update(cx, |view, cx| {
4586 view.add_selection_below(&AddSelectionBelow, cx);
4587 assert_eq!(
4588 view.selection_ranges(cx),
4589 vec![
4590 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4591 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4592 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4593 DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
4594 ]
4595 );
4596 });
4597
4598 view.update(cx, |view, cx| {
4599 view.add_selection_above(&AddSelectionAbove, cx);
4600 assert_eq!(
4601 view.selection_ranges(cx),
4602 vec![
4603 DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
4604 DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
4605 DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
4606 ]
4607 );
4608 });
4609
4610 view.update(cx, |view, cx| {
4611 view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx)
4612 .unwrap();
4613 });
4614 view.update(cx, |view, cx| {
4615 view.add_selection_above(&AddSelectionAbove, cx);
4616 assert_eq!(
4617 view.selection_ranges(cx),
4618 vec![
4619 DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
4620 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
4621 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
4622 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
4623 ]
4624 );
4625 });
4626
4627 view.update(cx, |view, cx| {
4628 view.add_selection_below(&AddSelectionBelow, cx);
4629 assert_eq!(
4630 view.selection_ranges(cx),
4631 vec![
4632 DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
4633 DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
4634 DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
4635 ]
4636 );
4637 });
4638 }
4639
4640 #[gpui::test]
4641 async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) {
4642 let settings = cx.read(EditorSettings::test);
4643 let language = Some(Arc::new(Language::new(
4644 LanguageConfig::default(),
4645 tree_sitter_rust::language(),
4646 )));
4647
4648 let text = r#"
4649 use mod1::mod2::{mod3, mod4};
4650
4651 fn fn_1(param1: bool, param2: &str) {
4652 let var1 = "text";
4653 }
4654 "#
4655 .unindent();
4656
4657 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
4658 let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
4659 view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
4660 .await;
4661
4662 view.update(&mut cx, |view, cx| {
4663 view.select_display_ranges(
4664 &[
4665 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4666 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4667 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4668 ],
4669 cx,
4670 )
4671 .unwrap();
4672 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4673 });
4674 assert_eq!(
4675 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4676 &[
4677 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
4678 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4679 DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
4680 ]
4681 );
4682
4683 view.update(&mut cx, |view, cx| {
4684 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4685 });
4686 assert_eq!(
4687 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4688 &[
4689 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4690 DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
4691 ]
4692 );
4693
4694 view.update(&mut cx, |view, cx| {
4695 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4696 });
4697 assert_eq!(
4698 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4699 &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
4700 );
4701
4702 // Trying to expand the selected syntax node one more time has no effect.
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 view.update(&mut cx, |view, cx| {
4712 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4713 });
4714 assert_eq!(
4715 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4716 &[
4717 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4718 DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
4719 ]
4720 );
4721
4722 view.update(&mut cx, |view, cx| {
4723 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4724 });
4725 assert_eq!(
4726 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4727 &[
4728 DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
4729 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4730 DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
4731 ]
4732 );
4733
4734 view.update(&mut cx, |view, cx| {
4735 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4736 });
4737 assert_eq!(
4738 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4739 &[
4740 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4741 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4742 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4743 ]
4744 );
4745
4746 // Trying to shrink the selected syntax node one more time has no effect.
4747 view.update(&mut cx, |view, cx| {
4748 view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
4749 });
4750 assert_eq!(
4751 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4752 &[
4753 DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
4754 DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
4755 DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
4756 ]
4757 );
4758
4759 // Ensure that we keep expanding the selection if the larger selection starts or ends within
4760 // a fold.
4761 view.update(&mut cx, |view, cx| {
4762 view.fold_ranges(
4763 vec![
4764 Point::new(0, 21)..Point::new(0, 24),
4765 Point::new(3, 20)..Point::new(3, 22),
4766 ],
4767 cx,
4768 );
4769 view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
4770 });
4771 assert_eq!(
4772 view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
4773 &[
4774 DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
4775 DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
4776 DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
4777 ]
4778 );
4779 }
4780
4781 #[gpui::test]
4782 async fn test_autoclose_pairs(mut cx: gpui::TestAppContext) {
4783 let settings = cx.read(EditorSettings::test);
4784 let language = Some(Arc::new(Language::new(
4785 LanguageConfig {
4786 brackets: vec![
4787 BracketPair {
4788 start: "{".to_string(),
4789 end: "}".to_string(),
4790 close: true,
4791 newline: true,
4792 },
4793 BracketPair {
4794 start: "/*".to_string(),
4795 end: " */".to_string(),
4796 close: true,
4797 newline: true,
4798 },
4799 ],
4800 ..Default::default()
4801 },
4802 tree_sitter_rust::language(),
4803 )));
4804
4805 let text = r#"
4806 a
4807
4808 /
4809
4810 "#
4811 .unindent();
4812
4813 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
4814 let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
4815 view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
4816 .await;
4817
4818 view.update(&mut cx, |view, cx| {
4819 view.select_display_ranges(
4820 &[
4821 DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4822 DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4823 ],
4824 cx,
4825 )
4826 .unwrap();
4827 view.handle_input(&Input("{".to_string()), cx);
4828 view.handle_input(&Input("{".to_string()), cx);
4829 view.handle_input(&Input("{".to_string()), cx);
4830 assert_eq!(
4831 view.text(cx),
4832 "
4833 {{{}}}
4834 {{{}}}
4835 /
4836
4837 "
4838 .unindent()
4839 );
4840
4841 view.move_right(&MoveRight, cx);
4842 view.handle_input(&Input("}".to_string()), cx);
4843 view.handle_input(&Input("}".to_string()), cx);
4844 view.handle_input(&Input("}".to_string()), cx);
4845 assert_eq!(
4846 view.text(cx),
4847 "
4848 {{{}}}}
4849 {{{}}}}
4850 /
4851
4852 "
4853 .unindent()
4854 );
4855
4856 view.undo(&Undo, cx);
4857 view.handle_input(&Input("/".to_string()), cx);
4858 view.handle_input(&Input("*".to_string()), cx);
4859 assert_eq!(
4860 view.text(cx),
4861 "
4862 /* */
4863 /* */
4864 /
4865
4866 "
4867 .unindent()
4868 );
4869
4870 view.undo(&Undo, cx);
4871 view.select_display_ranges(
4872 &[
4873 DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4874 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4875 ],
4876 cx,
4877 )
4878 .unwrap();
4879 view.handle_input(&Input("*".to_string()), cx);
4880 assert_eq!(
4881 view.text(cx),
4882 "
4883 a
4884
4885 /*
4886 *
4887 "
4888 .unindent()
4889 );
4890 });
4891 }
4892
4893 #[gpui::test]
4894 async fn test_extra_newline_insertion(mut cx: gpui::TestAppContext) {
4895 let settings = cx.read(EditorSettings::test);
4896 let language = Some(Arc::new(Language::new(
4897 LanguageConfig {
4898 brackets: vec![
4899 BracketPair {
4900 start: "{".to_string(),
4901 end: "}".to_string(),
4902 close: true,
4903 newline: true,
4904 },
4905 BracketPair {
4906 start: "/* ".to_string(),
4907 end: " */".to_string(),
4908 close: true,
4909 newline: true,
4910 },
4911 ],
4912 ..Default::default()
4913 },
4914 tree_sitter_rust::language(),
4915 )));
4916
4917 let text = concat!(
4918 "{ }\n", // Suppress rustfmt
4919 " x\n", //
4920 " /* */\n", //
4921 "x\n", //
4922 "{{} }\n", //
4923 );
4924
4925 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
4926 let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
4927 view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
4928 .await;
4929
4930 view.update(&mut cx, |view, cx| {
4931 view.select_display_ranges(
4932 &[
4933 DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
4934 DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
4935 DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
4936 ],
4937 cx,
4938 )
4939 .unwrap();
4940 view.newline(&Newline, cx);
4941
4942 assert_eq!(
4943 view.buffer().read(cx).text(),
4944 concat!(
4945 "{ \n", // Suppress rustfmt
4946 "\n", //
4947 "}\n", //
4948 " x\n", //
4949 " /* \n", //
4950 " \n", //
4951 " */\n", //
4952 "x\n", //
4953 "{{} \n", //
4954 "}\n", //
4955 )
4956 );
4957 });
4958 }
4959
4960 impl Editor {
4961 fn selection_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
4962 self.selections_in_range(
4963 self.selection_set_id,
4964 DisplayPoint::zero()..self.max_point(cx),
4965 cx,
4966 )
4967 .collect::<Vec<_>>()
4968 }
4969 }
4970
4971 fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
4972 let point = DisplayPoint::new(row as u32, column as u32);
4973 point..point
4974 }
4975
4976 fn build_editor(
4977 buffer: ModelHandle<Buffer>,
4978 settings: EditorSettings,
4979 cx: &mut ViewContext<Editor>,
4980 ) -> Editor {
4981 Editor::for_buffer(buffer, move |_| settings.clone(), cx)
4982 }
4983}
4984
4985trait RangeExt<T> {
4986 fn sorted(&self) -> Range<T>;
4987 fn to_inclusive(&self) -> RangeInclusive<T>;
4988}
4989
4990impl<T: Ord + Clone> RangeExt<T> for Range<T> {
4991 fn sorted(&self) -> Self {
4992 cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
4993 }
4994
4995 fn to_inclusive(&self) -> RangeInclusive<T> {
4996 self.start.clone()..=self.end.clone()
4997 }
4998}