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