1use std::{
2 cell::Ref,
3 cmp, fmt, iter, mem,
4 ops::{Deref, DerefMut, Range, Sub},
5 sync::Arc,
6};
7
8use collections::HashMap;
9use gpui::{App, Entity, Pixels};
10use itertools::Itertools;
11use language::{Bias, Point, Selection, SelectionGoal, TextDimension};
12use util::post_inc;
13
14use crate::{
15 Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode,
16 ToOffset, ToPoint,
17 display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
18 movement::TextLayoutDetails,
19};
20
21#[derive(Debug, Clone)]
22pub struct PendingSelection {
23 pub selection: Selection<Anchor>,
24 pub mode: SelectMode,
25}
26
27#[derive(Debug, Clone)]
28pub struct SelectionsCollection {
29 display_map: Entity<DisplayMap>,
30 buffer: Entity<MultiBuffer>,
31 next_selection_id: usize,
32 line_mode: bool,
33 /// The non-pending, non-overlapping selections.
34 /// The [SelectionsCollection::pending] selection could possibly overlap these
35 disjoint: Arc<[Selection<Anchor>]>,
36 /// A pending selection, such as when the mouse is being dragged
37 pending: Option<PendingSelection>,
38}
39
40impl SelectionsCollection {
41 pub fn new(display_map: Entity<DisplayMap>, buffer: Entity<MultiBuffer>) -> Self {
42 Self {
43 display_map,
44 buffer,
45 next_selection_id: 1,
46 line_mode: false,
47 disjoint: Arc::default(),
48 pending: Some(PendingSelection {
49 selection: Selection {
50 id: 0,
51 start: Anchor::min(),
52 end: Anchor::min(),
53 reversed: false,
54 goal: SelectionGoal::None,
55 },
56 mode: SelectMode::Character,
57 }),
58 }
59 }
60
61 pub fn display_map(&self, cx: &mut App) -> DisplaySnapshot {
62 self.display_map.update(cx, |map, cx| map.snapshot(cx))
63 }
64
65 fn buffer<'a>(&self, cx: &'a App) -> Ref<'a, MultiBufferSnapshot> {
66 self.buffer.read(cx).read(cx)
67 }
68
69 pub fn clone_state(&mut self, other: &SelectionsCollection) {
70 self.next_selection_id = other.next_selection_id;
71 self.line_mode = other.line_mode;
72 self.disjoint = other.disjoint.clone();
73 self.pending.clone_from(&other.pending);
74 }
75
76 pub fn count(&self) -> usize {
77 let mut count = self.disjoint.len();
78 if self.pending.is_some() {
79 count += 1;
80 }
81 count
82 }
83
84 /// The non-pending, non-overlapping selections. There could be a pending selection that
85 /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
86 /// pending selection. Returned as selections over Anchors.
87 pub fn disjoint_anchors_arc(&self) -> Arc<[Selection<Anchor>]> {
88 self.disjoint.clone()
89 }
90
91 /// The non-pending, non-overlapping selections. There could be a pending selection that
92 /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
93 /// pending selection. Returned as selections over Anchors.
94 pub fn disjoint_anchors(&self) -> &[Selection<Anchor>] {
95 &self.disjoint
96 }
97
98 pub fn disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> {
99 // Mapping the Arc slice would borrow it, whereas indexing captures it.
100 let disjoint = self.disjoint_anchors_arc();
101 (0..disjoint.len()).map(move |ix| disjoint[ix].range())
102 }
103
104 /// Non-overlapping selections using anchors, including the pending selection.
105 pub fn all_anchors(&self, cx: &mut App) -> Arc<[Selection<Anchor>]> {
106 if self.pending.is_none() {
107 self.disjoint_anchors_arc()
108 } else {
109 let all_offset_selections = self.all::<usize>(cx);
110 let buffer = self.buffer(cx);
111 all_offset_selections
112 .into_iter()
113 .map(|selection| selection_to_anchor_selection(selection, &buffer))
114 .collect()
115 }
116 }
117
118 pub fn pending_anchor(&self) -> Option<&Selection<Anchor>> {
119 self.pending.as_ref().map(|pending| &pending.selection)
120 }
121
122 pub fn pending_anchor_mut(&mut self) -> Option<&mut Selection<Anchor>> {
123 self.pending.as_mut().map(|pending| &mut pending.selection)
124 }
125
126 pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
127 &self,
128 cx: &mut App,
129 ) -> Option<Selection<D>> {
130 let map = self.display_map(cx);
131
132 resolve_selections(self.pending_anchor(), &map).next()
133 }
134
135 pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
136 self.pending.as_ref().map(|pending| pending.mode.clone())
137 }
138
139 pub fn all<'a, D>(&self, cx: &mut App) -> Vec<Selection<D>>
140 where
141 D: 'a + TextDimension + Ord + Sub<D, Output = D>,
142 {
143 let map = self.display_map(cx);
144 let disjoint_anchors = &self.disjoint;
145 let mut disjoint = resolve_selections::<D, _>(disjoint_anchors.iter(), &map).peekable();
146 let mut pending_opt = self.pending::<D>(cx);
147 iter::from_fn(move || {
148 if let Some(pending) = pending_opt.as_mut() {
149 while let Some(next_selection) = disjoint.peek() {
150 if pending.start <= next_selection.end && pending.end >= next_selection.start {
151 let next_selection = disjoint.next().unwrap();
152 if next_selection.start < pending.start {
153 pending.start = next_selection.start;
154 }
155 if next_selection.end > pending.end {
156 pending.end = next_selection.end;
157 }
158 } else if next_selection.end < pending.start {
159 return disjoint.next();
160 } else {
161 break;
162 }
163 }
164
165 pending_opt.take()
166 } else {
167 disjoint.next()
168 }
169 })
170 .collect()
171 }
172
173 /// Returns all of the selections, adjusted to take into account the selection line_mode
174 pub fn all_adjusted(&self, cx: &mut App) -> Vec<Selection<Point>> {
175 let mut selections = self.all::<Point>(cx);
176 if self.line_mode {
177 let map = self.display_map(cx);
178 for selection in &mut selections {
179 let new_range = map.expand_to_line(selection.range());
180 selection.start = new_range.start;
181 selection.end = new_range.end;
182 }
183 }
184 selections
185 }
186
187 /// Returns the newest selection, adjusted to take into account the selection line_mode
188 pub fn newest_adjusted(&self, cx: &mut App) -> Selection<Point> {
189 let mut selection = self.newest::<Point>(cx);
190 if self.line_mode {
191 let map = self.display_map(cx);
192 let new_range = map.expand_to_line(selection.range());
193 selection.start = new_range.start;
194 selection.end = new_range.end;
195 }
196 selection
197 }
198
199 pub fn all_adjusted_display(
200 &self,
201 cx: &mut App,
202 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
203 if self.line_mode {
204 let selections = self.all::<Point>(cx);
205 let map = self.display_map(cx);
206 let result = selections
207 .into_iter()
208 .map(|mut selection| {
209 let new_range = map.expand_to_line(selection.range());
210 selection.start = new_range.start;
211 selection.end = new_range.end;
212 selection.map(|point| point.to_display_point(&map))
213 })
214 .collect();
215 (map, result)
216 } else {
217 self.all_display(cx)
218 }
219 }
220
221 pub fn disjoint_in_range<'a, D>(&self, range: Range<Anchor>, cx: &mut App) -> Vec<Selection<D>>
222 where
223 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
224 {
225 let map = self.display_map(cx);
226 let start_ix = match self
227 .disjoint
228 .binary_search_by(|probe| probe.end.cmp(&range.start, &map.buffer_snapshot))
229 {
230 Ok(ix) | Err(ix) => ix,
231 };
232 let end_ix = match self
233 .disjoint
234 .binary_search_by(|probe| probe.start.cmp(&range.end, &map.buffer_snapshot))
235 {
236 Ok(ix) => ix + 1,
237 Err(ix) => ix,
238 };
239 resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect()
240 }
241
242 pub fn all_display(&self, cx: &mut App) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
243 let map = self.display_map(cx);
244 let disjoint_anchors = &self.disjoint;
245 let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable();
246 let mut pending_opt = resolve_selections_display(self.pending_anchor(), &map).next();
247 let selections = iter::from_fn(move || {
248 if let Some(pending) = pending_opt.as_mut() {
249 while let Some(next_selection) = disjoint.peek() {
250 if pending.start <= next_selection.end && pending.end >= next_selection.start {
251 let next_selection = disjoint.next().unwrap();
252 if next_selection.start < pending.start {
253 pending.start = next_selection.start;
254 }
255 if next_selection.end > pending.end {
256 pending.end = next_selection.end;
257 }
258 } else if next_selection.end < pending.start {
259 return disjoint.next();
260 } else {
261 break;
262 }
263 }
264
265 pending_opt.take()
266 } else {
267 disjoint.next()
268 }
269 })
270 .collect();
271 (map, selections)
272 }
273
274 pub fn newest_anchor(&self) -> &Selection<Anchor> {
275 self.pending
276 .as_ref()
277 .map(|s| &s.selection)
278 .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
279 .unwrap()
280 }
281
282 pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
283 &self,
284 cx: &mut App,
285 ) -> Selection<D> {
286 let map = self.display_map(cx);
287
288 resolve_selections([self.newest_anchor()], &map)
289 .next()
290 .unwrap()
291 }
292
293 pub fn newest_display(&self, cx: &mut App) -> Selection<DisplayPoint> {
294 let map = self.display_map(cx);
295
296 resolve_selections_display([self.newest_anchor()], &map)
297 .next()
298 .unwrap()
299 }
300
301 pub fn oldest_anchor(&self) -> &Selection<Anchor> {
302 self.disjoint
303 .iter()
304 .min_by_key(|s| s.id)
305 .or_else(|| self.pending.as_ref().map(|p| &p.selection))
306 .unwrap()
307 }
308
309 pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
310 &self,
311 cx: &mut App,
312 ) -> Selection<D> {
313 let map = self.display_map(cx);
314
315 resolve_selections([self.oldest_anchor()], &map)
316 .next()
317 .unwrap()
318 }
319
320 pub fn first_anchor(&self) -> Selection<Anchor> {
321 self.pending
322 .as_ref()
323 .map(|pending| pending.selection.clone())
324 .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
325 }
326
327 pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
328 self.all(cx).first().unwrap().clone()
329 }
330
331 pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(&self, cx: &mut App) -> Selection<D> {
332 self.all(cx).last().unwrap().clone()
333 }
334
335 pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
336 &self,
337 cx: &mut App,
338 ) -> Vec<Range<D>> {
339 self.all::<D>(cx)
340 .iter()
341 .map(|s| {
342 if s.reversed {
343 s.end..s.start
344 } else {
345 s.start..s.end
346 }
347 })
348 .collect()
349 }
350
351 #[cfg(any(test, feature = "test-support"))]
352 pub fn display_ranges(&self, cx: &mut App) -> Vec<Range<DisplayPoint>> {
353 let display_map = self.display_map(cx);
354 self.disjoint_anchors_arc()
355 .iter()
356 .chain(self.pending_anchor())
357 .map(|s| {
358 if s.reversed {
359 s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
360 } else {
361 s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
362 }
363 })
364 .collect()
365 }
366
367 pub fn build_columnar_selection(
368 &mut self,
369 display_map: &DisplaySnapshot,
370 row: DisplayRow,
371 positions: &Range<Pixels>,
372 reversed: bool,
373 text_layout_details: &TextLayoutDetails,
374 ) -> Option<Selection<Point>> {
375 let is_empty = positions.start == positions.end;
376 let line_len = display_map.line_len(row);
377 let line = display_map.layout_row(row, text_layout_details);
378 let start_col = line.closest_index_for_x(positions.start) as u32;
379
380 let (start, end) = if is_empty {
381 let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
382 (point, point)
383 } else {
384 if start_col >= line_len {
385 return None;
386 }
387 let start = DisplayPoint::new(row, start_col);
388 let end_col = line.closest_index_for_x(positions.end) as u32;
389 let end = DisplayPoint::new(row, end_col);
390 (start, end)
391 };
392
393 Some(Selection {
394 id: post_inc(&mut self.next_selection_id),
395 start: start.to_point(display_map),
396 end: end.to_point(display_map),
397 reversed,
398 goal: SelectionGoal::HorizontalRange {
399 start: positions.start.into(),
400 end: positions.end.into(),
401 },
402 })
403 }
404
405 pub fn change_with<R>(
406 &mut self,
407 cx: &mut App,
408 change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
409 ) -> (bool, R) {
410 let mut mutable_collection = MutableSelectionsCollection {
411 collection: self,
412 selections_changed: false,
413 cx,
414 };
415
416 let result = change(&mut mutable_collection);
417 assert!(
418 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
419 "There must be at least one selection"
420 );
421 (mutable_collection.selections_changed, result)
422 }
423
424 pub fn next_selection_id(&self) -> usize {
425 self.next_selection_id
426 }
427
428 pub fn line_mode(&self) -> bool {
429 self.line_mode
430 }
431
432 pub fn set_line_mode(&mut self, line_mode: bool) {
433 self.line_mode = line_mode;
434 }
435}
436
437pub struct MutableSelectionsCollection<'a> {
438 collection: &'a mut SelectionsCollection,
439 selections_changed: bool,
440 cx: &'a mut App,
441}
442
443impl<'a> fmt::Debug for MutableSelectionsCollection<'a> {
444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445 f.debug_struct("MutableSelectionsCollection")
446 .field("collection", &self.collection)
447 .field("selections_changed", &self.selections_changed)
448 .finish()
449 }
450}
451
452impl<'a> MutableSelectionsCollection<'a> {
453 pub fn display_map(&mut self) -> DisplaySnapshot {
454 self.collection.display_map(self.cx)
455 }
456
457 pub fn buffer(&self) -> Ref<'_, MultiBufferSnapshot> {
458 self.collection.buffer(self.cx)
459 }
460
461 pub fn clear_disjoint(&mut self) {
462 self.collection.disjoint = Arc::default();
463 }
464
465 pub fn delete(&mut self, selection_id: usize) {
466 let mut changed = false;
467 self.collection.disjoint = self
468 .disjoint
469 .iter()
470 .filter(|selection| {
471 let found = selection.id == selection_id;
472 changed |= found;
473 !found
474 })
475 .cloned()
476 .collect();
477
478 self.selections_changed |= changed;
479 }
480
481 pub fn clear_pending(&mut self) {
482 if self.collection.pending.is_some() {
483 self.collection.pending = None;
484 self.selections_changed = true;
485 }
486 }
487
488 pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
489 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
490 self.collection.pending = Some(PendingSelection {
491 selection: {
492 let mut start = range.start;
493 let mut end = range.end;
494 let reversed = if start.cmp(&end, &buffer).is_gt() {
495 mem::swap(&mut start, &mut end);
496 true
497 } else {
498 false
499 };
500 Selection {
501 id: post_inc(&mut self.collection.next_selection_id),
502 start,
503 end,
504 reversed,
505 goal: SelectionGoal::None,
506 }
507 },
508 mode,
509 });
510 self.selections_changed = true;
511 }
512
513 pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
514 self.collection.pending = Some(PendingSelection { selection, mode });
515 self.selections_changed = true;
516 }
517
518 pub fn try_cancel(&mut self) -> bool {
519 if let Some(pending) = self.collection.pending.take() {
520 if self.disjoint.is_empty() {
521 self.collection.disjoint = Arc::from([pending.selection]);
522 }
523 self.selections_changed = true;
524 return true;
525 }
526
527 let mut oldest = self.oldest_anchor().clone();
528 if self.count() > 1 {
529 self.collection.disjoint = Arc::from([oldest]);
530 self.selections_changed = true;
531 return true;
532 }
533
534 if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
535 let head = oldest.head();
536 oldest.start = head;
537 oldest.end = head;
538 self.collection.disjoint = Arc::from([oldest]);
539 self.selections_changed = true;
540 return true;
541 }
542
543 false
544 }
545
546 pub fn insert_range<T>(&mut self, range: Range<T>)
547 where
548 T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
549 {
550 let mut selections = self.collection.all(self.cx);
551 let mut start = range.start.to_offset(&self.buffer());
552 let mut end = range.end.to_offset(&self.buffer());
553 let reversed = if start > end {
554 mem::swap(&mut start, &mut end);
555 true
556 } else {
557 false
558 };
559 selections.push(Selection {
560 id: post_inc(&mut self.collection.next_selection_id),
561 start,
562 end,
563 reversed,
564 goal: SelectionGoal::None,
565 });
566 self.select(selections);
567 }
568
569 pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
570 where
571 T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
572 {
573 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
574 selections.sort_unstable_by_key(|s| s.start);
575 // Merge overlapping selections.
576 let mut i = 1;
577 while i < selections.len() {
578 if selections[i - 1].end >= selections[i].start {
579 let removed = selections.remove(i);
580 if removed.start < selections[i - 1].start {
581 selections[i - 1].start = removed.start;
582 }
583 if removed.end > selections[i - 1].end {
584 selections[i - 1].end = removed.end;
585 }
586 } else {
587 i += 1;
588 }
589 }
590
591 self.collection.disjoint = Arc::from_iter(
592 selections
593 .into_iter()
594 .map(|selection| selection_to_anchor_selection(selection, &buffer)),
595 );
596 self.collection.pending = None;
597 self.selections_changed = true;
598 }
599
600 pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
601 let map = self.display_map();
602 let resolved_selections =
603 resolve_selections::<usize, _>(&selections, &map).collect::<Vec<_>>();
604 self.select(resolved_selections);
605 }
606
607 pub fn select_ranges<I, T>(&mut self, ranges: I)
608 where
609 I: IntoIterator<Item = Range<T>>,
610 T: ToOffset,
611 {
612 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
613 let ranges = ranges
614 .into_iter()
615 .map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer));
616 self.select_offset_ranges(ranges);
617 }
618
619 fn select_offset_ranges<I>(&mut self, ranges: I)
620 where
621 I: IntoIterator<Item = Range<usize>>,
622 {
623 let selections = ranges
624 .into_iter()
625 .map(|range| {
626 let mut start = range.start;
627 let mut end = range.end;
628 let reversed = if start > end {
629 mem::swap(&mut start, &mut end);
630 true
631 } else {
632 false
633 };
634 Selection {
635 id: post_inc(&mut self.collection.next_selection_id),
636 start,
637 end,
638 reversed,
639 goal: SelectionGoal::None,
640 }
641 })
642 .collect::<Vec<_>>();
643
644 self.select(selections)
645 }
646
647 pub fn select_anchor_ranges<I>(&mut self, ranges: I)
648 where
649 I: IntoIterator<Item = Range<Anchor>>,
650 {
651 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
652 let selections = ranges
653 .into_iter()
654 .map(|range| {
655 let mut start = range.start;
656 let mut end = range.end;
657 let reversed = if start.cmp(&end, &buffer).is_gt() {
658 mem::swap(&mut start, &mut end);
659 true
660 } else {
661 false
662 };
663 Selection {
664 id: post_inc(&mut self.collection.next_selection_id),
665 start,
666 end,
667 reversed,
668 goal: SelectionGoal::None,
669 }
670 })
671 .collect::<Vec<_>>();
672 self.select_anchors(selections)
673 }
674
675 pub fn new_selection_id(&mut self) -> usize {
676 post_inc(&mut self.next_selection_id)
677 }
678
679 pub fn select_display_ranges<T>(&mut self, ranges: T)
680 where
681 T: IntoIterator<Item = Range<DisplayPoint>>,
682 {
683 let display_map = self.display_map();
684 let selections = ranges
685 .into_iter()
686 .map(|range| {
687 let mut start = range.start;
688 let mut end = range.end;
689 let reversed = if start > end {
690 mem::swap(&mut start, &mut end);
691 true
692 } else {
693 false
694 };
695 Selection {
696 id: post_inc(&mut self.collection.next_selection_id),
697 start: start.to_point(&display_map),
698 end: end.to_point(&display_map),
699 reversed,
700 goal: SelectionGoal::None,
701 }
702 })
703 .collect();
704 self.select(selections);
705 }
706
707 pub fn reverse_selections(&mut self) {
708 let map = &self.display_map();
709 let mut new_selections: Vec<Selection<Point>> = Vec::new();
710 let disjoint = self.disjoint.clone();
711 for selection in disjoint
712 .iter()
713 .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
714 .collect::<Vec<&Selection<Anchor>>>()
715 {
716 new_selections.push(Selection {
717 id: self.new_selection_id(),
718 start: selection.start.to_display_point(map).to_point(map),
719 end: selection.end.to_display_point(map).to_point(map),
720 reversed: selection.reversed,
721 goal: selection.goal,
722 });
723 }
724 self.select(new_selections);
725 }
726
727 pub fn move_with(
728 &mut self,
729 mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
730 ) {
731 let mut changed = false;
732 let display_map = self.display_map();
733 let (_, selections) = self.collection.all_display(self.cx);
734 let selections = selections
735 .into_iter()
736 .map(|selection| {
737 let mut moved_selection = selection.clone();
738 move_selection(&display_map, &mut moved_selection);
739 if selection != moved_selection {
740 changed = true;
741 }
742 moved_selection.map(|display_point| display_point.to_point(&display_map))
743 })
744 .collect();
745
746 if changed {
747 self.select(selections)
748 }
749 }
750
751 pub fn move_offsets_with(
752 &mut self,
753 mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
754 ) {
755 let mut changed = false;
756 let snapshot = self.buffer().clone();
757 let selections = self
758 .collection
759 .all::<usize>(self.cx)
760 .into_iter()
761 .map(|selection| {
762 let mut moved_selection = selection.clone();
763 move_selection(&snapshot, &mut moved_selection);
764 if selection != moved_selection {
765 changed = true;
766 }
767 moved_selection
768 })
769 .collect();
770 drop(snapshot);
771
772 if changed {
773 self.select(selections)
774 }
775 }
776
777 pub fn move_heads_with(
778 &mut self,
779 mut update_head: impl FnMut(
780 &DisplaySnapshot,
781 DisplayPoint,
782 SelectionGoal,
783 ) -> (DisplayPoint, SelectionGoal),
784 ) {
785 self.move_with(|map, selection| {
786 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
787 selection.set_head(new_head, new_goal);
788 });
789 }
790
791 pub fn move_cursors_with(
792 &mut self,
793 mut update_cursor_position: impl FnMut(
794 &DisplaySnapshot,
795 DisplayPoint,
796 SelectionGoal,
797 ) -> (DisplayPoint, SelectionGoal),
798 ) {
799 self.move_with(|map, selection| {
800 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
801 selection.collapse_to(cursor, new_goal)
802 });
803 }
804
805 pub fn maybe_move_cursors_with(
806 &mut self,
807 mut update_cursor_position: impl FnMut(
808 &DisplaySnapshot,
809 DisplayPoint,
810 SelectionGoal,
811 ) -> Option<(DisplayPoint, SelectionGoal)>,
812 ) {
813 self.move_cursors_with(|map, point, goal| {
814 update_cursor_position(map, point, goal).unwrap_or((point, goal))
815 })
816 }
817
818 pub fn replace_cursors_with(
819 &mut self,
820 find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
821 ) {
822 let display_map = self.display_map();
823 let new_selections = find_replacement_cursors(&display_map)
824 .into_iter()
825 .map(|cursor| {
826 let cursor_point = cursor.to_point(&display_map);
827 Selection {
828 id: post_inc(&mut self.collection.next_selection_id),
829 start: cursor_point,
830 end: cursor_point,
831 reversed: false,
832 goal: SelectionGoal::None,
833 }
834 })
835 .collect();
836 self.select(new_selections);
837 }
838
839 /// Compute new ranges for any selections that were located in excerpts that have
840 /// since been removed.
841 ///
842 /// Returns a `HashMap` indicating which selections whose former head position
843 /// was no longer present. The keys of the map are selection ids. The values are
844 /// the id of the new excerpt where the head of the selection has been moved.
845 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
846 let mut pending = self.collection.pending.take();
847 let mut selections_with_lost_position = HashMap::default();
848
849 let anchors_with_status = {
850 let buffer = self.buffer();
851 let disjoint_anchors = self
852 .disjoint
853 .iter()
854 .flat_map(|selection| [&selection.start, &selection.end]);
855 buffer.refresh_anchors(disjoint_anchors)
856 };
857 let adjusted_disjoint: Vec<_> = anchors_with_status
858 .chunks(2)
859 .map(|selection_anchors| {
860 let (anchor_ix, start, kept_start) = selection_anchors[0];
861 let (_, end, kept_end) = selection_anchors[1];
862 let selection = &self.disjoint[anchor_ix / 2];
863 let kept_head = if selection.reversed {
864 kept_start
865 } else {
866 kept_end
867 };
868 if !kept_head {
869 selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
870 }
871
872 Selection {
873 id: selection.id,
874 start,
875 end,
876 reversed: selection.reversed,
877 goal: selection.goal,
878 }
879 })
880 .collect();
881
882 if !adjusted_disjoint.is_empty() {
883 let map = self.display_map();
884 let resolved_selections = resolve_selections(adjusted_disjoint.iter(), &map).collect();
885 self.select::<usize>(resolved_selections);
886 }
887
888 if let Some(pending) = pending.as_mut() {
889 let buffer = self.buffer();
890 let anchors =
891 buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
892 let (_, start, kept_start) = anchors[0];
893 let (_, end, kept_end) = anchors[1];
894 let kept_head = if pending.selection.reversed {
895 kept_start
896 } else {
897 kept_end
898 };
899 if !kept_head {
900 selections_with_lost_position
901 .insert(pending.selection.id, pending.selection.head().excerpt_id);
902 }
903
904 pending.selection.start = start;
905 pending.selection.end = end;
906 }
907 self.collection.pending = pending;
908 self.selections_changed = true;
909
910 selections_with_lost_position
911 }
912}
913
914impl Deref for MutableSelectionsCollection<'_> {
915 type Target = SelectionsCollection;
916 fn deref(&self) -> &Self::Target {
917 self.collection
918 }
919}
920
921impl DerefMut for MutableSelectionsCollection<'_> {
922 fn deref_mut(&mut self) -> &mut Self::Target {
923 self.collection
924 }
925}
926
927fn selection_to_anchor_selection<T>(
928 selection: Selection<T>,
929 buffer: &MultiBufferSnapshot,
930) -> Selection<Anchor>
931where
932 T: ToOffset + Ord,
933{
934 let end_bias = if selection.start == selection.end {
935 Bias::Right
936 } else {
937 Bias::Left
938 };
939 Selection {
940 id: selection.id,
941 start: buffer.anchor_after(selection.start),
942 end: buffer.anchor_at(selection.end, end_bias),
943 reversed: selection.reversed,
944 goal: selection.goal,
945 }
946}
947
948fn resolve_selections_point<'a>(
949 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
950 map: &'a DisplaySnapshot,
951) -> impl 'a + Iterator<Item = Selection<Point>> {
952 let (to_summarize, selections) = selections.into_iter().tee();
953 let mut summaries = map
954 .buffer_snapshot
955 .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
956 .into_iter();
957 selections.map(move |s| {
958 let start = summaries.next().unwrap();
959 let end = summaries.next().unwrap();
960 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
961 Selection {
962 id: s.id,
963 start,
964 end,
965 reversed: s.reversed,
966 goal: s.goal,
967 }
968 })
969}
970
971// Panics if passed selections are not in order
972fn resolve_selections_display<'a>(
973 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
974 map: &'a DisplaySnapshot,
975) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
976 let selections = resolve_selections_point(selections, map).map(move |s| {
977 let display_start = map.point_to_display_point(s.start, Bias::Left);
978 let display_end = map.point_to_display_point(
979 s.end,
980 if s.start == s.end {
981 Bias::Right
982 } else {
983 Bias::Left
984 },
985 );
986 assert!(
987 display_start <= display_end,
988 "display_start: {:?}, display_end: {:?}",
989 display_start,
990 display_end
991 );
992 Selection {
993 id: s.id,
994 start: display_start,
995 end: display_end,
996 reversed: s.reversed,
997 goal: s.goal,
998 }
999 });
1000 coalesce_selections(selections)
1001}
1002
1003// Panics if passed selections are not in order
1004pub(crate) fn resolve_selections<'a, D, I>(
1005 selections: I,
1006 map: &'a DisplaySnapshot,
1007) -> impl 'a + Iterator<Item = Selection<D>>
1008where
1009 D: TextDimension + Ord + Sub<D, Output = D>,
1010 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1011{
1012 let (to_convert, selections) = resolve_selections_display(selections, map).tee();
1013 let mut converted_endpoints =
1014 map.buffer_snapshot
1015 .dimensions_from_points::<D>(to_convert.flat_map(|s| {
1016 let start = map.display_point_to_point(s.start, Bias::Left);
1017 let end = map.display_point_to_point(s.end, Bias::Right);
1018 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1019 [start, end]
1020 }));
1021 selections.map(move |s| {
1022 let start = converted_endpoints.next().unwrap();
1023 let end = converted_endpoints.next().unwrap();
1024 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1025 Selection {
1026 id: s.id,
1027 start,
1028 end,
1029 reversed: s.reversed,
1030 goal: s.goal,
1031 }
1032 })
1033}
1034
1035fn coalesce_selections<D: Ord + fmt::Debug + Copy>(
1036 selections: impl Iterator<Item = Selection<D>>,
1037) -> impl Iterator<Item = Selection<D>> {
1038 let mut selections = selections.peekable();
1039 iter::from_fn(move || {
1040 let mut selection = selections.next()?;
1041 while let Some(next_selection) = selections.peek() {
1042 if selection.end >= next_selection.start {
1043 if selection.reversed == next_selection.reversed {
1044 selection.end = cmp::max(selection.end, next_selection.end);
1045 selections.next();
1046 } else {
1047 selection.end = cmp::max(selection.start, next_selection.start);
1048 break;
1049 }
1050 } else {
1051 break;
1052 }
1053 }
1054 assert!(
1055 selection.start <= selection.end,
1056 "selection.start: {:?}, selection.end: {:?}, selection.reversed: {:?}",
1057 selection.start,
1058 selection.end,
1059 selection.reversed
1060 );
1061 Some(selection)
1062 })
1063}