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