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 should_merge(
140 pending.start,
141 pending.end,
142 next_selection.start,
143 next_selection.end,
144 false,
145 ) {
146 let next_selection = disjoint.next().unwrap();
147 if next_selection.start < pending.start {
148 pending.start = next_selection.start;
149 }
150 if next_selection.end > pending.end {
151 pending.end = next_selection.end;
152 }
153 } else if next_selection.end < pending.start {
154 return disjoint.next();
155 } else {
156 break;
157 }
158 }
159
160 pending_opt.take()
161 } else {
162 disjoint.next()
163 }
164 })
165 .collect()
166 }
167
168 /// Returns all of the selections, adjusted to take into account the selection line_mode
169 pub fn all_adjusted(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<Point>> {
170 let mut selections = self.all::<Point>(&snapshot);
171 if self.line_mode {
172 for selection in &mut selections {
173 let new_range = snapshot.expand_to_line(selection.range());
174 selection.start = new_range.start;
175 selection.end = new_range.end;
176 }
177 }
178 selections
179 }
180
181 /// Returns the newest selection, adjusted to take into account the selection line_mode
182 pub fn newest_adjusted(&self, snapshot: &DisplaySnapshot) -> Selection<Point> {
183 let mut selection = self.newest::<Point>(&snapshot);
184 if self.line_mode {
185 let new_range = snapshot.expand_to_line(selection.range());
186 selection.start = new_range.start;
187 selection.end = new_range.end;
188 }
189 selection
190 }
191
192 pub fn all_adjusted_display(
193 &self,
194 display_map: &DisplaySnapshot,
195 ) -> Vec<Selection<DisplayPoint>> {
196 if self.line_mode {
197 let selections = self.all::<Point>(&display_map);
198 let result = selections
199 .into_iter()
200 .map(|mut selection| {
201 let new_range = display_map.expand_to_line(selection.range());
202 selection.start = new_range.start;
203 selection.end = new_range.end;
204 selection.map(|point| point.to_display_point(&display_map))
205 })
206 .collect();
207 result
208 } else {
209 self.all_display(display_map)
210 }
211 }
212
213 pub fn disjoint_in_range<D>(
214 &self,
215 range: Range<Anchor>,
216 snapshot: &DisplaySnapshot,
217 ) -> Vec<Selection<D>>
218 where
219 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord + std::fmt::Debug,
220 {
221 let start_ix = match self
222 .disjoint
223 .binary_search_by(|probe| probe.end.cmp(&range.start, snapshot.buffer_snapshot()))
224 {
225 Ok(ix) | Err(ix) => ix,
226 };
227 let end_ix = match self
228 .disjoint
229 .binary_search_by(|probe| probe.start.cmp(&range.end, snapshot.buffer_snapshot()))
230 {
231 Ok(ix) => ix + 1,
232 Err(ix) => ix,
233 };
234 resolve_selections_wrapping_blocks(&self.disjoint[start_ix..end_ix], snapshot).collect()
235 }
236
237 pub fn all_display(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<DisplayPoint>> {
238 let disjoint_anchors = &self.disjoint;
239 let mut disjoint =
240 resolve_selections_display(disjoint_anchors.iter(), &snapshot).peekable();
241 let mut pending_opt = resolve_selections_display(self.pending_anchor(), &snapshot).next();
242 iter::from_fn(move || {
243 if let Some(pending) = pending_opt.as_mut() {
244 while let Some(next_selection) = disjoint.peek() {
245 if should_merge(
246 pending.start,
247 pending.end,
248 next_selection.start,
249 next_selection.end,
250 false,
251 ) {
252 let next_selection = disjoint.next().unwrap();
253 if next_selection.start < pending.start {
254 pending.start = next_selection.start;
255 }
256 if next_selection.end > pending.end {
257 pending.end = next_selection.end;
258 }
259 } else if next_selection.end < pending.start {
260 return disjoint.next();
261 } else {
262 break;
263 }
264 }
265
266 pending_opt.take()
267 } else {
268 disjoint.next()
269 }
270 })
271 .collect()
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>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
283 where
284 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
285 {
286 resolve_selections_wrapping_blocks([self.newest_anchor()], &snapshot)
287 .next()
288 .unwrap()
289 }
290
291 pub fn newest_display(&self, snapshot: &DisplaySnapshot) -> Selection<DisplayPoint> {
292 resolve_selections_display([self.newest_anchor()], &snapshot)
293 .next()
294 .unwrap()
295 }
296
297 pub fn oldest_anchor(&self) -> &Selection<Anchor> {
298 self.disjoint
299 .iter()
300 .min_by_key(|s| s.id)
301 .or_else(|| self.pending.as_ref().map(|p| &p.selection))
302 .unwrap()
303 }
304
305 pub fn oldest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
306 where
307 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
308 {
309 resolve_selections_wrapping_blocks([self.oldest_anchor()], &snapshot)
310 .next()
311 .unwrap()
312 }
313
314 pub fn first_anchor(&self) -> Selection<Anchor> {
315 self.pending
316 .as_ref()
317 .map(|pending| pending.selection.clone())
318 .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
319 }
320
321 pub fn first<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
322 where
323 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
324 {
325 self.all(snapshot).first().unwrap().clone()
326 }
327
328 pub fn last<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
329 where
330 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
331 {
332 self.all(snapshot).last().unwrap().clone()
333 }
334
335 /// Returns a list of (potentially backwards!) ranges representing the selections.
336 /// Useful for test assertions, but prefer `.all()` instead.
337 #[cfg(any(test, feature = "test-support"))]
338 pub fn ranges<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Range<D>>
339 where
340 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
341 {
342 self.all::<D>(snapshot)
343 .iter()
344 .map(|s| {
345 if s.reversed {
346 s.end..s.start
347 } else {
348 s.start..s.end
349 }
350 })
351 .collect()
352 }
353
354 #[cfg(any(test, feature = "test-support"))]
355 pub fn display_ranges(&self, display_snapshot: &DisplaySnapshot) -> Vec<Range<DisplayPoint>> {
356 self.disjoint_anchors_arc()
357 .iter()
358 .chain(self.pending_anchor())
359 .map(|s| {
360 if s.reversed {
361 s.end.to_display_point(display_snapshot)
362 ..s.start.to_display_point(display_snapshot)
363 } else {
364 s.start.to_display_point(display_snapshot)
365 ..s.end.to_display_point(display_snapshot)
366 }
367 })
368 .collect()
369 }
370
371 /// Attempts to build a selection in the provided `DisplayRow` within the
372 /// same range as the provided range of `Pixels`.
373 /// Returns `None` if the range is not empty but it starts past the line's
374 /// length, meaning that the line isn't long enough to be contained within
375 /// part of the provided range.
376 pub fn build_columnar_selection(
377 &mut self,
378 display_map: &DisplaySnapshot,
379 row: DisplayRow,
380 positions: &Range<Pixels>,
381 reversed: bool,
382 text_layout_details: &TextLayoutDetails,
383 ) -> Option<Selection<Point>> {
384 let is_empty = positions.start == positions.end;
385 let line_len = display_map.line_len(row);
386 let line = display_map.layout_row(row, text_layout_details);
387 let start_col = line.closest_index_for_x(positions.start) as u32;
388
389 let (start, end) = if is_empty {
390 let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
391 (point, point)
392 } else {
393 if start_col >= line_len {
394 return None;
395 }
396 let start = DisplayPoint::new(row, start_col);
397 let end_col = line.closest_index_for_x(positions.end) as u32;
398 let end = DisplayPoint::new(row, end_col);
399 (start, end)
400 };
401
402 Some(Selection {
403 id: post_inc(&mut self.next_selection_id),
404 start: start.to_point(display_map),
405 end: end.to_point(display_map),
406 reversed,
407 goal: SelectionGoal::HorizontalRange {
408 start: positions.start.into(),
409 end: positions.end.into(),
410 },
411 })
412 }
413
414 /// Attempts to build a selection in the provided buffer row using the
415 /// same buffer column range as specified.
416 /// Returns `None` if the range is not empty but it starts past the line's
417 /// length, meaning that the line isn't long enough to be contained within
418 /// part of the provided range.
419 pub fn build_columnar_selection_from_buffer_columns(
420 &mut self,
421 display_map: &DisplaySnapshot,
422 buffer_row: u32,
423 positions: &Range<u32>,
424 reversed: bool,
425 text_layout_details: &TextLayoutDetails,
426 ) -> Option<Selection<Point>> {
427 let is_empty = positions.start == positions.end;
428 let line_len = display_map
429 .buffer_snapshot()
430 .line_len(multi_buffer::MultiBufferRow(buffer_row));
431
432 let (start, end) = if is_empty {
433 let column = std::cmp::min(positions.start, line_len);
434 let point = Point::new(buffer_row, column);
435 (point, point)
436 } else {
437 if positions.start >= line_len {
438 return None;
439 }
440
441 let start = Point::new(buffer_row, positions.start);
442 let end_column = std::cmp::min(positions.end, line_len);
443 let end = Point::new(buffer_row, end_column);
444 (start, end)
445 };
446
447 let start_display_point = start.to_display_point(display_map);
448 let end_display_point = end.to_display_point(display_map);
449 let start_x = display_map.x_for_display_point(start_display_point, text_layout_details);
450 let end_x = display_map.x_for_display_point(end_display_point, text_layout_details);
451
452 Some(Selection {
453 id: post_inc(&mut self.next_selection_id),
454 start,
455 end,
456 reversed,
457 goal: SelectionGoal::HorizontalRange {
458 start: start_x.min(end_x).into(),
459 end: start_x.max(end_x).into(),
460 },
461 })
462 }
463
464 /// Finds the next columnar selection by walking display rows one at a time
465 /// so that soft-wrapped lines are considered and not skipped.
466 pub fn find_next_columnar_selection_by_display_row(
467 &mut self,
468 display_map: &DisplaySnapshot,
469 start_row: DisplayRow,
470 end_row: DisplayRow,
471 above: bool,
472 positions: &Range<Pixels>,
473 reversed: bool,
474 text_layout_details: &TextLayoutDetails,
475 ) -> Option<Selection<Point>> {
476 let mut row = start_row;
477 while row != end_row {
478 if above {
479 row.0 -= 1;
480 } else {
481 row.0 += 1;
482 }
483
484 if let Some(selection) = self.build_columnar_selection(
485 display_map,
486 row,
487 positions,
488 reversed,
489 text_layout_details,
490 ) {
491 return Some(selection);
492 }
493 }
494 None
495 }
496
497 /// Finds the next columnar selection by skipping to the next buffer row,
498 /// ignoring soft-wrapped lines.
499 pub fn find_next_columnar_selection_by_buffer_row(
500 &mut self,
501 display_map: &DisplaySnapshot,
502 start_row: DisplayRow,
503 end_row: DisplayRow,
504 above: bool,
505 goal_columns: &Range<u32>,
506 reversed: bool,
507 text_layout_details: &TextLayoutDetails,
508 ) -> Option<Selection<Point>> {
509 let mut row = start_row;
510 let direction = if above { -1 } else { 1 };
511 while row != end_row {
512 let new_row =
513 display_map.start_of_relative_buffer_row(DisplayPoint::new(row, 0), direction);
514 row = new_row.row();
515 let buffer_row = new_row.to_point(display_map).row;
516
517 if let Some(selection) = self.build_columnar_selection_from_buffer_columns(
518 display_map,
519 buffer_row,
520 goal_columns,
521 reversed,
522 text_layout_details,
523 ) {
524 return Some(selection);
525 }
526 }
527 None
528 }
529
530 pub fn change_with<R>(
531 &mut self,
532 snapshot: &DisplaySnapshot,
533 change: impl FnOnce(&mut MutableSelectionsCollection<'_, '_>) -> R,
534 ) -> (bool, R) {
535 let mut mutable_collection = MutableSelectionsCollection {
536 snapshot,
537 collection: self,
538 selections_changed: false,
539 };
540
541 let result = change(&mut mutable_collection);
542 assert!(
543 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
544 "There must be at least one selection"
545 );
546 if cfg!(debug_assertions) {
547 mutable_collection.disjoint.iter().for_each(|selection| {
548 assert!(
549 snapshot.can_resolve(&selection.start),
550 "disjoint selection start is not resolvable for the given snapshot:\n{selection:?}, {excerpt:?}",
551 excerpt = snapshot.buffer_for_excerpt(selection.start.excerpt_id).map(|snapshot| snapshot.remote_id()),
552 );
553 assert!(
554 snapshot.can_resolve(&selection.end),
555 "disjoint selection end is not resolvable for the given snapshot: {selection:?}, {excerpt:?}",
556 excerpt = snapshot.buffer_for_excerpt(selection.end.excerpt_id).map(|snapshot| snapshot.remote_id()),
557 );
558 });
559 if let Some(pending) = &mutable_collection.pending {
560 let selection = &pending.selection;
561 assert!(
562 snapshot.can_resolve(&selection.start),
563 "pending selection start is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
564 excerpt = snapshot
565 .buffer_for_excerpt(selection.start.excerpt_id)
566 .map(|snapshot| snapshot.remote_id()),
567 );
568 assert!(
569 snapshot.can_resolve(&selection.end),
570 "pending selection end is not resolvable for the given snapshot: {pending:?}, {excerpt:?}",
571 excerpt = snapshot
572 .buffer_for_excerpt(selection.end.excerpt_id)
573 .map(|snapshot| snapshot.remote_id()),
574 );
575 }
576 }
577 (mutable_collection.selections_changed, result)
578 }
579
580 pub fn next_selection_id(&self) -> usize {
581 self.next_selection_id
582 }
583
584 pub fn line_mode(&self) -> bool {
585 self.line_mode
586 }
587
588 pub fn set_line_mode(&mut self, line_mode: bool) {
589 self.line_mode = line_mode;
590 }
591
592 pub fn select_mode(&self) -> &SelectMode {
593 &self.select_mode
594 }
595
596 pub fn set_select_mode(&mut self, select_mode: SelectMode) {
597 self.select_mode = select_mode;
598 }
599
600 pub fn is_extending(&self) -> bool {
601 self.is_extending
602 }
603
604 pub fn set_is_extending(&mut self, is_extending: bool) {
605 self.is_extending = is_extending;
606 }
607}
608
609pub struct MutableSelectionsCollection<'snap, 'a> {
610 collection: &'a mut SelectionsCollection,
611 snapshot: &'snap DisplaySnapshot,
612 selections_changed: bool,
613}
614
615impl<'snap, 'a> fmt::Debug for MutableSelectionsCollection<'snap, 'a> {
616 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617 f.debug_struct("MutableSelectionsCollection")
618 .field("collection", &self.collection)
619 .field("selections_changed", &self.selections_changed)
620 .finish()
621 }
622}
623
624impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
625 pub fn display_snapshot(&self) -> DisplaySnapshot {
626 self.snapshot.clone()
627 }
628
629 pub fn clear_disjoint(&mut self) {
630 self.collection.disjoint = Arc::default();
631 }
632
633 pub fn delete(&mut self, selection_id: usize) {
634 let mut changed = false;
635 self.collection.disjoint = self
636 .disjoint
637 .iter()
638 .filter(|selection| {
639 let found = selection.id == selection_id;
640 changed |= found;
641 !found
642 })
643 .cloned()
644 .collect();
645
646 self.selections_changed |= changed;
647 }
648
649 pub fn remove_selections_from_buffer(&mut self, buffer_id: language::BufferId) {
650 let mut changed = false;
651
652 let filtered_selections: Arc<[Selection<Anchor>]> = {
653 self.disjoint
654 .iter()
655 .filter(|selection| {
656 if let Some(selection_buffer_id) =
657 self.snapshot.buffer_id_for_anchor(selection.start)
658 {
659 let should_remove = selection_buffer_id == buffer_id;
660 changed |= should_remove;
661 !should_remove
662 } else {
663 true
664 }
665 })
666 .cloned()
667 .collect()
668 };
669
670 if filtered_selections.is_empty() {
671 let buffer_snapshot = self.snapshot.buffer_snapshot();
672 let anchor = buffer_snapshot
673 .excerpts()
674 .find(|(_, buffer, _)| buffer.remote_id() == buffer_id)
675 .and_then(|(excerpt_id, _, range)| {
676 buffer_snapshot.anchor_in_excerpt(excerpt_id, range.context.start)
677 })
678 .unwrap_or_else(|| self.snapshot.anchor_before(MultiBufferOffset(0)));
679 self.collection.disjoint = Arc::from([Selection {
680 id: post_inc(&mut self.collection.next_selection_id),
681 start: anchor,
682 end: anchor,
683 reversed: false,
684 goal: SelectionGoal::None,
685 }]);
686 } else {
687 self.collection.disjoint = filtered_selections;
688 }
689
690 self.selections_changed |= changed;
691 }
692
693 pub fn clear_pending(&mut self) {
694 if self.collection.pending.is_some() {
695 self.collection.pending = None;
696 self.selections_changed = true;
697 }
698 }
699
700 pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
701 self.collection.pending = Some(PendingSelection {
702 selection: {
703 let mut start = range.start;
704 let mut end = range.end;
705 let reversed = if start.cmp(&end, self.snapshot).is_gt() {
706 mem::swap(&mut start, &mut end);
707 true
708 } else {
709 false
710 };
711 Selection {
712 id: post_inc(&mut self.collection.next_selection_id),
713 start,
714 end,
715 reversed,
716 goal: SelectionGoal::None,
717 }
718 },
719 mode,
720 });
721 self.selections_changed = true;
722 }
723
724 pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
725 self.collection.pending = Some(PendingSelection { selection, mode });
726 self.selections_changed = true;
727 }
728
729 pub fn try_cancel(&mut self) -> bool {
730 if let Some(pending) = self.collection.pending.take() {
731 if self.disjoint.is_empty() {
732 self.collection.disjoint = Arc::from([pending.selection]);
733 }
734 self.selections_changed = true;
735 return true;
736 }
737
738 let mut oldest = self.oldest_anchor().clone();
739 if self.count() > 1 {
740 self.collection.disjoint = Arc::from([oldest]);
741 self.selections_changed = true;
742 return true;
743 }
744
745 if !oldest.start.cmp(&oldest.end, self.snapshot).is_eq() {
746 let head = oldest.head();
747 oldest.start = head;
748 oldest.end = head;
749 self.collection.disjoint = Arc::from([oldest]);
750 self.selections_changed = true;
751 return true;
752 }
753
754 false
755 }
756
757 pub fn insert_range<T>(&mut self, range: Range<T>)
758 where
759 T: ToOffset,
760 {
761 let display_map = self.display_snapshot();
762 let mut selections = self.collection.all(&display_map);
763 let mut start = range.start.to_offset(self.snapshot);
764 let mut end = range.end.to_offset(self.snapshot);
765 let reversed = if start > end {
766 mem::swap(&mut start, &mut end);
767 true
768 } else {
769 false
770 };
771 selections.push(Selection {
772 id: post_inc(&mut self.collection.next_selection_id),
773 start,
774 end,
775 reversed,
776 goal: SelectionGoal::None,
777 });
778 self.select(selections);
779 }
780
781 pub fn select<T>(&mut self, selections: Vec<Selection<T>>)
782 where
783 T: ToOffset + std::marker::Copy + std::fmt::Debug,
784 {
785 let mut selections = selections
786 .into_iter()
787 .map(|selection| selection.map(|it| it.to_offset(self.snapshot)))
788 .map(|mut selection| {
789 if selection.start > selection.end {
790 mem::swap(&mut selection.start, &mut selection.end);
791 selection.reversed = true
792 }
793 selection
794 })
795 .collect::<Vec<_>>();
796 selections.sort_unstable_by_key(|s| s.start);
797
798 let mut i = 1;
799 while i < selections.len() {
800 let prev = &selections[i - 1];
801 let current = &selections[i];
802
803 if should_merge(prev.start, prev.end, current.start, current.end, true) {
804 let removed = selections.remove(i);
805 if removed.start < selections[i - 1].start {
806 selections[i - 1].start = removed.start;
807 }
808 if selections[i - 1].end < removed.end {
809 selections[i - 1].end = removed.end;
810 }
811 } else {
812 i += 1;
813 }
814 }
815
816 self.collection.disjoint = Arc::from_iter(
817 selections
818 .into_iter()
819 .map(|selection| selection_to_anchor_selection(selection, self.snapshot)),
820 );
821 self.collection.pending = None;
822 self.selections_changed = true;
823 }
824
825 pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
826 let map = self.display_snapshot();
827 let resolved_selections =
828 resolve_selections_wrapping_blocks::<MultiBufferOffset, _>(&selections, &map)
829 .collect::<Vec<_>>();
830 self.select(resolved_selections);
831 }
832
833 pub fn select_ranges<I, T>(&mut self, ranges: I)
834 where
835 I: IntoIterator<Item = Range<T>>,
836 T: ToOffset,
837 {
838 let ranges = ranges
839 .into_iter()
840 .map(|range| range.start.to_offset(self.snapshot)..range.end.to_offset(self.snapshot));
841 self.select_offset_ranges(ranges);
842 }
843
844 fn select_offset_ranges<I>(&mut self, ranges: I)
845 where
846 I: IntoIterator<Item = Range<MultiBufferOffset>>,
847 {
848 let selections = ranges
849 .into_iter()
850 .map(|range| {
851 let mut start = range.start;
852 let mut end = range.end;
853 let reversed = if start > end {
854 mem::swap(&mut start, &mut end);
855 true
856 } else {
857 false
858 };
859 Selection {
860 id: post_inc(&mut self.collection.next_selection_id),
861 start,
862 end,
863 reversed,
864 goal: SelectionGoal::None,
865 }
866 })
867 .collect::<Vec<_>>();
868
869 self.select(selections)
870 }
871
872 pub fn select_anchor_ranges<I>(&mut self, ranges: I)
873 where
874 I: IntoIterator<Item = Range<Anchor>>,
875 {
876 let selections = ranges
877 .into_iter()
878 .map(|range| {
879 let mut start = range.start;
880 let mut end = range.end;
881 let reversed = if start.cmp(&end, self.snapshot).is_gt() {
882 mem::swap(&mut start, &mut end);
883 true
884 } else {
885 false
886 };
887 Selection {
888 id: post_inc(&mut self.collection.next_selection_id),
889 start,
890 end,
891 reversed,
892 goal: SelectionGoal::None,
893 }
894 })
895 .collect::<Vec<_>>();
896 self.select_anchors(selections)
897 }
898
899 pub fn new_selection_id(&mut self) -> usize {
900 post_inc(&mut self.next_selection_id)
901 }
902
903 pub fn select_display_ranges<T>(&mut self, ranges: T)
904 where
905 T: IntoIterator<Item = Range<DisplayPoint>>,
906 {
907 let selections = ranges
908 .into_iter()
909 .map(|range| {
910 let mut start = range.start;
911 let mut end = range.end;
912 let reversed = if start > end {
913 mem::swap(&mut start, &mut end);
914 true
915 } else {
916 false
917 };
918 Selection {
919 id: post_inc(&mut self.collection.next_selection_id),
920 start: start.to_point(self.snapshot),
921 end: end.to_point(self.snapshot),
922 reversed,
923 goal: SelectionGoal::None,
924 }
925 })
926 .collect();
927 self.select(selections);
928 }
929
930 pub fn reverse_selections(&mut self) {
931 let mut new_selections: Vec<Selection<Point>> = Vec::new();
932 let disjoint = self.disjoint.clone();
933 for selection in disjoint
934 .iter()
935 .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
936 .collect::<Vec<&Selection<Anchor>>>()
937 {
938 new_selections.push(Selection {
939 id: self.new_selection_id(),
940 start: selection
941 .start
942 .to_display_point(self.snapshot)
943 .to_point(self.snapshot),
944 end: selection
945 .end
946 .to_display_point(self.snapshot)
947 .to_point(self.snapshot),
948 reversed: selection.reversed,
949 goal: selection.goal,
950 });
951 }
952 self.select(new_selections);
953 }
954
955 pub fn move_with(
956 &mut self,
957 mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
958 ) {
959 let mut changed = false;
960 let display_map = self.display_snapshot();
961 let selections = self.collection.all_display(&display_map);
962 let selections = selections
963 .into_iter()
964 .map(|selection| {
965 let mut moved_selection = selection.clone();
966 move_selection(&display_map, &mut moved_selection);
967 if selection != moved_selection {
968 changed = true;
969 }
970 moved_selection.map(|display_point| display_point.to_point(&display_map))
971 })
972 .collect();
973
974 if changed {
975 self.select(selections)
976 }
977 }
978
979 pub fn move_offsets_with(
980 &mut self,
981 mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
982 ) {
983 let mut changed = false;
984 let display_map = self.display_snapshot();
985 let selections = self
986 .collection
987 .all::<MultiBufferOffset>(&display_map)
988 .into_iter()
989 .map(|selection| {
990 let mut moved_selection = selection.clone();
991 move_selection(self.snapshot, &mut moved_selection);
992 if selection != moved_selection {
993 changed = true;
994 }
995 moved_selection
996 })
997 .collect();
998
999 if changed {
1000 self.select(selections)
1001 }
1002 }
1003
1004 pub fn move_heads_with(
1005 &mut self,
1006 mut update_head: impl FnMut(
1007 &DisplaySnapshot,
1008 DisplayPoint,
1009 SelectionGoal,
1010 ) -> (DisplayPoint, SelectionGoal),
1011 ) {
1012 self.move_with(|map, selection| {
1013 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
1014 selection.set_head(new_head, new_goal);
1015 });
1016 }
1017
1018 pub fn move_cursors_with(
1019 &mut self,
1020 mut update_cursor_position: impl FnMut(
1021 &DisplaySnapshot,
1022 DisplayPoint,
1023 SelectionGoal,
1024 ) -> (DisplayPoint, SelectionGoal),
1025 ) {
1026 self.move_with(|map, selection| {
1027 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
1028 selection.collapse_to(cursor, new_goal)
1029 });
1030 }
1031
1032 pub fn maybe_move_cursors_with(
1033 &mut self,
1034 mut update_cursor_position: impl FnMut(
1035 &DisplaySnapshot,
1036 DisplayPoint,
1037 SelectionGoal,
1038 ) -> Option<(DisplayPoint, SelectionGoal)>,
1039 ) {
1040 self.move_cursors_with(|map, point, goal| {
1041 update_cursor_position(map, point, goal).unwrap_or((point, goal))
1042 })
1043 }
1044
1045 pub fn replace_cursors_with(
1046 &mut self,
1047 find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
1048 ) {
1049 let new_selections = find_replacement_cursors(self.snapshot)
1050 .into_iter()
1051 .map(|cursor| {
1052 let cursor_point = cursor.to_point(self.snapshot);
1053 Selection {
1054 id: post_inc(&mut self.collection.next_selection_id),
1055 start: cursor_point,
1056 end: cursor_point,
1057 reversed: false,
1058 goal: SelectionGoal::None,
1059 }
1060 })
1061 .collect();
1062 self.select(new_selections);
1063 }
1064
1065 /// Compute new ranges for any selections that were located in excerpts that have
1066 /// since been removed.
1067 ///
1068 /// Returns a `HashMap` indicating which selections whose former head position
1069 /// was no longer present. The keys of the map are selection ids. The values are
1070 /// the id of the new excerpt where the head of the selection has been moved.
1071 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
1072 let mut pending = self.collection.pending.take();
1073 let mut selections_with_lost_position = HashMap::default();
1074
1075 let anchors_with_status = {
1076 let disjoint_anchors = self
1077 .disjoint
1078 .iter()
1079 .flat_map(|selection| [&selection.start, &selection.end]);
1080 self.snapshot.refresh_anchors(disjoint_anchors)
1081 };
1082 let adjusted_disjoint: Vec<_> = anchors_with_status
1083 .chunks(2)
1084 .map(|selection_anchors| {
1085 let (anchor_ix, start, kept_start) = selection_anchors[0];
1086 let (_, end, kept_end) = selection_anchors[1];
1087 let selection = &self.disjoint[anchor_ix / 2];
1088 let kept_head = if selection.reversed {
1089 kept_start
1090 } else {
1091 kept_end
1092 };
1093 if !kept_head {
1094 selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
1095 }
1096
1097 Selection {
1098 id: selection.id,
1099 start,
1100 end,
1101 reversed: selection.reversed,
1102 goal: selection.goal,
1103 }
1104 })
1105 .collect();
1106
1107 if !adjusted_disjoint.is_empty() {
1108 let map = self.display_snapshot();
1109 let resolved_selections =
1110 resolve_selections_wrapping_blocks(adjusted_disjoint.iter(), &map).collect();
1111 self.select::<MultiBufferOffset>(resolved_selections);
1112 }
1113
1114 if let Some(pending) = pending.as_mut() {
1115 let anchors = self
1116 .snapshot
1117 .refresh_anchors([&pending.selection.start, &pending.selection.end]);
1118 let (_, start, kept_start) = anchors[0];
1119 let (_, end, kept_end) = anchors[1];
1120 let kept_head = if pending.selection.reversed {
1121 kept_start
1122 } else {
1123 kept_end
1124 };
1125 if !kept_head {
1126 selections_with_lost_position
1127 .insert(pending.selection.id, pending.selection.head().excerpt_id);
1128 }
1129
1130 pending.selection.start = start;
1131 pending.selection.end = end;
1132 }
1133 self.collection.pending = pending;
1134 self.selections_changed = true;
1135
1136 selections_with_lost_position
1137 }
1138}
1139
1140impl Deref for MutableSelectionsCollection<'_, '_> {
1141 type Target = SelectionsCollection;
1142 fn deref(&self) -> &Self::Target {
1143 self.collection
1144 }
1145}
1146
1147impl DerefMut for MutableSelectionsCollection<'_, '_> {
1148 fn deref_mut(&mut self) -> &mut Self::Target {
1149 self.collection
1150 }
1151}
1152
1153fn selection_to_anchor_selection(
1154 selection: Selection<MultiBufferOffset>,
1155 buffer: &MultiBufferSnapshot,
1156) -> Selection<Anchor> {
1157 let end_bias = if selection.start == selection.end {
1158 Bias::Right
1159 } else {
1160 Bias::Left
1161 };
1162 Selection {
1163 id: selection.id,
1164 start: buffer.anchor_after(selection.start),
1165 end: buffer.anchor_at(selection.end, end_bias),
1166 reversed: selection.reversed,
1167 goal: selection.goal,
1168 }
1169}
1170
1171fn resolve_selections_point<'a>(
1172 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1173 map: &'a DisplaySnapshot,
1174) -> impl 'a + Iterator<Item = Selection<Point>> {
1175 let (to_summarize, selections) = selections.into_iter().tee();
1176 let mut summaries = map
1177 .buffer_snapshot()
1178 .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
1179 .into_iter();
1180 selections.map(move |s| {
1181 let start = summaries.next().unwrap();
1182 let end = summaries.next().unwrap();
1183 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1184 Selection {
1185 id: s.id,
1186 start,
1187 end,
1188 reversed: s.reversed,
1189 goal: s.goal,
1190 }
1191 })
1192}
1193
1194/// Panics if passed selections are not in order
1195/// Resolves the anchors to display positions
1196fn resolve_selections_display<'a>(
1197 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1198 map: &'a DisplaySnapshot,
1199) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
1200 let selections = resolve_selections_point(selections, map).map(move |s| {
1201 let display_start = map.point_to_display_point(s.start, Bias::Left);
1202 let display_end = map.point_to_display_point(
1203 s.end,
1204 if s.start == s.end {
1205 Bias::Right
1206 } else {
1207 Bias::Left
1208 },
1209 );
1210 assert!(
1211 display_start <= display_end,
1212 "display_start: {:?}, display_end: {:?}",
1213 display_start,
1214 display_end
1215 );
1216 Selection {
1217 id: s.id,
1218 start: display_start,
1219 end: display_end,
1220 reversed: s.reversed,
1221 goal: s.goal,
1222 }
1223 });
1224 coalesce_selections(selections)
1225}
1226
1227/// Resolves the passed in anchors to [`MultiBufferDimension`]s `D`
1228/// wrapping around blocks inbetween.
1229///
1230/// # Panics
1231///
1232/// Panics if passed selections are not in order
1233pub(crate) fn resolve_selections_wrapping_blocks<'a, D, I>(
1234 selections: I,
1235 map: &'a DisplaySnapshot,
1236) -> impl 'a + Iterator<Item = Selection<D>>
1237where
1238 D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
1239 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
1240{
1241 // Transforms `Anchor -> DisplayPoint -> Point -> DisplayPoint -> D`
1242 // todo(lw): We should be able to short circuit the `Anchor -> DisplayPoint -> Point` to `Anchor -> Point`
1243 let (to_convert, selections) = resolve_selections_display(selections, map).tee();
1244 let mut converted_endpoints =
1245 map.buffer_snapshot()
1246 .dimensions_from_points::<D>(to_convert.flat_map(|s| {
1247 let start = map.display_point_to_point(s.start, Bias::Left);
1248 let end = map.display_point_to_point(s.end, Bias::Right);
1249 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1250 [start, end]
1251 }));
1252 selections.map(move |s| {
1253 let start = converted_endpoints.next().unwrap();
1254 let end = converted_endpoints.next().unwrap();
1255 assert!(start <= end, "start: {:?}, end: {:?}", start, end);
1256 Selection {
1257 id: s.id,
1258 start,
1259 end,
1260 reversed: s.reversed,
1261 goal: s.goal,
1262 }
1263 })
1264}
1265
1266fn coalesce_selections<D: Ord + fmt::Debug + Copy>(
1267 selections: impl Iterator<Item = Selection<D>>,
1268) -> impl Iterator<Item = Selection<D>> {
1269 let mut selections = selections.peekable();
1270 iter::from_fn(move || {
1271 let mut selection = selections.next()?;
1272 while let Some(next_selection) = selections.peek() {
1273 if should_merge(
1274 selection.start,
1275 selection.end,
1276 next_selection.start,
1277 next_selection.end,
1278 true,
1279 ) {
1280 if selection.reversed == next_selection.reversed {
1281 selection.end = cmp::max(selection.end, next_selection.end);
1282 selections.next();
1283 } else {
1284 selection.end = cmp::max(selection.start, next_selection.start);
1285 break;
1286 }
1287 } else {
1288 break;
1289 }
1290 }
1291 assert!(
1292 selection.start <= selection.end,
1293 "selection.start: {:?}, selection.end: {:?}, selection.reversed: {:?}",
1294 selection.start,
1295 selection.end,
1296 selection.reversed
1297 );
1298 Some(selection)
1299 })
1300}
1301
1302/// Determines whether two selections should be merged into one.
1303///
1304/// Two selections should be merged when:
1305/// 1. They overlap: the selections share at least one position
1306/// 2. They have the same start position: one contains or equals the other
1307/// 3. A cursor touches a selection boundary: a zero-width selection (cursor) at the
1308/// start or end of another selection should be absorbed into it
1309///
1310/// Note: two selections that merely touch (one ends exactly where the other begins)
1311/// but don't share any positions remain separate, see: https://github.com/zed-industries/zed/issues/24748
1312fn should_merge<T: Ord + Copy>(a_start: T, a_end: T, b_start: T, b_end: T, sorted: bool) -> bool {
1313 let is_overlapping = if sorted {
1314 // When sorted, `a` starts before or at `b`, so overlap means `b` starts before `a` ends
1315 b_start < a_end
1316 } else {
1317 a_start < b_end && b_start < a_end
1318 };
1319
1320 // Selections starting at the same position should always merge (one contains the other)
1321 let same_start = a_start == b_start;
1322
1323 // A cursor (zero-width selection) touching another selection's boundary should merge.
1324 // This handles cases like a cursor at position X merging with a selection that
1325 // starts or ends at X.
1326 let is_cursor_a = a_start == a_end;
1327 let is_cursor_b = b_start == b_end;
1328 let cursor_at_boundary = (is_cursor_a && (a_start == b_start || a_end == b_end))
1329 || (is_cursor_b && (b_start == a_start || b_end == a_end));
1330
1331 is_overlapping || same_start || cursor_at_boundary
1332}