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