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