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