1use std::{
2 cell::Ref,
3 cmp, 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};
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, ToPoint,
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 disjoint_anchor_ranges(&self) -> impl Iterator<Item = Range<Anchor>> {
92 // Mapping the Arc slice would borrow it, whereas indexing captures it.
93 let disjoint = self.disjoint_anchors();
94 (0..disjoint.len()).map(move |ix| disjoint[ix].range())
95 }
96
97 pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
98 self.pending
99 .as_ref()
100 .map(|pending| pending.selection.clone())
101 }
102
103 pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
104 &self,
105 cx: &mut AppContext,
106 ) -> Option<Selection<D>> {
107 let map = self.display_map(cx);
108 let selection = resolve_selections(self.pending_anchor().as_ref(), &map).next();
109 selection
110 }
111
112 pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
113 self.pending.as_ref().map(|pending| pending.mode.clone())
114 }
115
116 pub fn all<'a, D>(&self, cx: &mut AppContext) -> Vec<Selection<D>>
117 where
118 D: 'a + TextDimension + Ord + Sub<D, Output = D>,
119 {
120 let map = self.display_map(cx);
121 let disjoint_anchors = &self.disjoint;
122 let mut disjoint = resolve_selections::<D, _>(disjoint_anchors.iter(), &map).peekable();
123 let mut pending_opt = self.pending::<D>(cx);
124 iter::from_fn(move || {
125 if let Some(pending) = pending_opt.as_mut() {
126 while let Some(next_selection) = disjoint.peek() {
127 if pending.start <= next_selection.end && pending.end >= next_selection.start {
128 let next_selection = disjoint.next().unwrap();
129 if next_selection.start < pending.start {
130 pending.start = next_selection.start;
131 }
132 if next_selection.end > pending.end {
133 pending.end = next_selection.end;
134 }
135 } else if next_selection.end < pending.start {
136 return disjoint.next();
137 } else {
138 break;
139 }
140 }
141
142 pending_opt.take()
143 } else {
144 disjoint.next()
145 }
146 })
147 .collect()
148 }
149
150 /// Returns all of the selections, adjusted to take into account the selection line_mode
151 pub fn all_adjusted(&self, cx: &mut AppContext) -> Vec<Selection<Point>> {
152 let mut selections = self.all::<Point>(cx);
153 if self.line_mode {
154 let map = self.display_map(cx);
155 for selection in &mut selections {
156 let new_range = map.expand_to_line(selection.range());
157 selection.start = new_range.start;
158 selection.end = new_range.end;
159 }
160 }
161 selections
162 }
163
164 /// Returns the newest selection, adjusted to take into account the selection line_mode
165 pub fn newest_adjusted(&self, cx: &mut AppContext) -> Selection<Point> {
166 let mut selection = self.newest::<Point>(cx);
167 if self.line_mode {
168 let map = self.display_map(cx);
169 let new_range = map.expand_to_line(selection.range());
170 selection.start = new_range.start;
171 selection.end = new_range.end;
172 }
173 selection
174 }
175
176 pub fn all_adjusted_display(
177 &self,
178 cx: &mut AppContext,
179 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
180 if self.line_mode {
181 let selections = self.all::<Point>(cx);
182 let map = self.display_map(cx);
183 let result = selections
184 .into_iter()
185 .map(|mut selection| {
186 let new_range = map.expand_to_line(selection.range());
187 selection.start = new_range.start;
188 selection.end = new_range.end;
189 selection.map(|point| point.to_display_point(&map))
190 })
191 .collect();
192 (map, result)
193 } else {
194 self.all_display(cx)
195 }
196 }
197
198 pub fn disjoint_in_range<'a, D>(
199 &self,
200 range: Range<Anchor>,
201 cx: &mut AppContext,
202 ) -> Vec<Selection<D>>
203 where
204 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
205 {
206 let map = self.display_map(cx);
207 let start_ix = match self
208 .disjoint
209 .binary_search_by(|probe| probe.end.cmp(&range.start, &map.buffer_snapshot))
210 {
211 Ok(ix) | Err(ix) => ix,
212 };
213 let end_ix = match self
214 .disjoint
215 .binary_search_by(|probe| probe.start.cmp(&range.end, &map.buffer_snapshot))
216 {
217 Ok(ix) => ix + 1,
218 Err(ix) => ix,
219 };
220 resolve_selections(&self.disjoint[start_ix..end_ix], &map).collect()
221 }
222
223 pub fn all_display(
224 &self,
225 cx: &mut AppContext,
226 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
227 let map = self.display_map(cx);
228 let disjoint_anchors = &self.disjoint;
229 let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable();
230 let mut pending_opt =
231 resolve_selections_display(self.pending_anchor().as_ref(), &map).next();
232 let selections = iter::from_fn(move || {
233 if let Some(pending) = pending_opt.as_mut() {
234 while let Some(next_selection) = disjoint.peek() {
235 if pending.start <= next_selection.end && pending.end >= next_selection.start {
236 let next_selection = disjoint.next().unwrap();
237 if next_selection.start < pending.start {
238 pending.start = next_selection.start;
239 }
240 if next_selection.end > pending.end {
241 pending.end = next_selection.end;
242 }
243 } else if next_selection.end < pending.start {
244 return disjoint.next();
245 } else {
246 break;
247 }
248 }
249
250 pending_opt.take()
251 } else {
252 disjoint.next()
253 }
254 })
255 .collect();
256 (map, selections)
257 }
258
259 pub fn newest_anchor(&self) -> &Selection<Anchor> {
260 self.pending
261 .as_ref()
262 .map(|s| &s.selection)
263 .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
264 .unwrap()
265 }
266
267 pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
268 &self,
269 cx: &mut AppContext,
270 ) -> Selection<D> {
271 let map = self.display_map(cx);
272 let selection = resolve_selections([self.newest_anchor()], &map)
273 .next()
274 .unwrap();
275 selection
276 }
277
278 pub fn newest_display(&self, cx: &mut AppContext) -> Selection<DisplayPoint> {
279 let map = self.display_map(cx);
280 let selection = resolve_selections_display([self.newest_anchor()], &map)
281 .next()
282 .unwrap();
283 selection
284 }
285
286 pub fn oldest_anchor(&self) -> &Selection<Anchor> {
287 self.disjoint
288 .iter()
289 .min_by_key(|s| s.id)
290 .or_else(|| self.pending.as_ref().map(|p| &p.selection))
291 .unwrap()
292 }
293
294 pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
295 &self,
296 cx: &mut AppContext,
297 ) -> Selection<D> {
298 let map = self.display_map(cx);
299 let selection = resolve_selections([self.oldest_anchor()], &map)
300 .next()
301 .unwrap();
302 selection
303 }
304
305 pub fn first_anchor(&self) -> Selection<Anchor> {
306 self.pending
307 .as_ref()
308 .map(|pending| pending.selection.clone())
309 .unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
310 }
311
312 pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
313 &self,
314 cx: &mut AppContext,
315 ) -> Selection<D> {
316 self.all(cx).first().unwrap().clone()
317 }
318
319 pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
320 &self,
321 cx: &mut AppContext,
322 ) -> Selection<D> {
323 self.all(cx).last().unwrap().clone()
324 }
325
326 #[cfg(any(test, feature = "test-support"))]
327 pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
328 &self,
329 cx: &mut AppContext,
330 ) -> Vec<Range<D>> {
331 self.all::<D>(cx)
332 .iter()
333 .map(|s| {
334 if s.reversed {
335 s.end.clone()..s.start.clone()
336 } else {
337 s.start.clone()..s.end.clone()
338 }
339 })
340 .collect()
341 }
342
343 #[cfg(any(test, feature = "test-support"))]
344 pub fn display_ranges(&self, cx: &mut AppContext) -> Vec<Range<DisplayPoint>> {
345 let display_map = self.display_map(cx);
346 self.disjoint_anchors()
347 .iter()
348 .chain(self.pending_anchor().as_ref())
349 .map(|s| {
350 if s.reversed {
351 s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
352 } else {
353 s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
354 }
355 })
356 .collect()
357 }
358
359 pub fn build_columnar_selection(
360 &mut self,
361 display_map: &DisplaySnapshot,
362 row: DisplayRow,
363 positions: &Range<Pixels>,
364 reversed: bool,
365 text_layout_details: &TextLayoutDetails,
366 ) -> Option<Selection<Point>> {
367 let is_empty = positions.start == positions.end;
368 let line_len = display_map.line_len(row);
369
370 let line = display_map.layout_row(row, text_layout_details);
371
372 let start_col = line.closest_index_for_x(positions.start) as u32;
373 if start_col < line_len || (is_empty && positions.start == line.width) {
374 let start = DisplayPoint::new(row, start_col);
375 let end_col = line.closest_index_for_x(positions.end) as u32;
376 let end = DisplayPoint::new(row, end_col);
377
378 Some(Selection {
379 id: post_inc(&mut self.next_selection_id),
380 start: start.to_point(display_map),
381 end: end.to_point(display_map),
382 reversed,
383 goal: SelectionGoal::HorizontalRange {
384 start: positions.start.into(),
385 end: positions.end.into(),
386 },
387 })
388 } else {
389 None
390 }
391 }
392
393 pub fn change_with<R>(
394 &mut self,
395 cx: &mut AppContext,
396 change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
397 ) -> (bool, R) {
398 let mut mutable_collection = MutableSelectionsCollection {
399 collection: self,
400 selections_changed: false,
401 cx,
402 };
403
404 let result = change(&mut mutable_collection);
405 assert!(
406 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
407 "There must be at least one selection"
408 );
409 (mutable_collection.selections_changed, result)
410 }
411}
412
413pub struct MutableSelectionsCollection<'a> {
414 collection: &'a mut SelectionsCollection,
415 selections_changed: bool,
416 cx: &'a mut AppContext,
417}
418
419impl<'a> MutableSelectionsCollection<'a> {
420 pub fn display_map(&mut self) -> DisplaySnapshot {
421 self.collection.display_map(self.cx)
422 }
423
424 pub fn buffer(&self) -> Ref<MultiBufferSnapshot> {
425 self.collection.buffer(self.cx)
426 }
427
428 pub fn clear_disjoint(&mut self) {
429 self.collection.disjoint = Arc::default();
430 }
431
432 pub fn delete(&mut self, selection_id: usize) {
433 let mut changed = false;
434 self.collection.disjoint = self
435 .disjoint
436 .iter()
437 .filter(|selection| {
438 let found = selection.id == selection_id;
439 changed |= found;
440 !found
441 })
442 .cloned()
443 .collect();
444
445 self.selections_changed |= changed;
446 }
447
448 pub fn clear_pending(&mut self) {
449 if self.collection.pending.is_some() {
450 self.collection.pending = None;
451 self.selections_changed = true;
452 }
453 }
454
455 pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
456 self.collection.pending = Some(PendingSelection {
457 selection: Selection {
458 id: post_inc(&mut self.collection.next_selection_id),
459 start: range.start,
460 end: range.end,
461 reversed: false,
462 goal: SelectionGoal::None,
463 },
464 mode,
465 });
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.collection.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 map = self.display_map();
568 let resolved_selections =
569 resolve_selections::<usize, _>(&selections, &map).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.collection.all_display(self.cx);
680 let selections = selections
681 .into_iter()
682 .map(|selection| {
683 let mut moved_selection = selection.clone();
684 move_selection(&display_map, &mut moved_selection);
685 if selection != moved_selection {
686 changed = true;
687 }
688 moved_selection.map(|display_point| display_point.to_point(&display_map))
689 })
690 .collect();
691
692 if changed {
693 self.select(selections)
694 }
695 }
696
697 pub fn move_offsets_with(
698 &mut self,
699 mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
700 ) {
701 let mut changed = false;
702 let snapshot = self.buffer().clone();
703 let selections = self
704 .collection
705 .all::<usize>(self.cx)
706 .into_iter()
707 .map(|selection| {
708 let mut moved_selection = selection.clone();
709 move_selection(&snapshot, &mut moved_selection);
710 if selection != moved_selection {
711 changed = true;
712 }
713 moved_selection
714 })
715 .collect();
716 drop(snapshot);
717
718 if changed {
719 self.select(selections)
720 }
721 }
722
723 pub fn move_heads_with(
724 &mut self,
725 mut update_head: impl FnMut(
726 &DisplaySnapshot,
727 DisplayPoint,
728 SelectionGoal,
729 ) -> (DisplayPoint, SelectionGoal),
730 ) {
731 self.move_with(|map, selection| {
732 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
733 selection.set_head(new_head, new_goal);
734 });
735 }
736
737 pub fn move_cursors_with(
738 &mut self,
739 mut update_cursor_position: impl FnMut(
740 &DisplaySnapshot,
741 DisplayPoint,
742 SelectionGoal,
743 ) -> (DisplayPoint, SelectionGoal),
744 ) {
745 self.move_with(|map, selection| {
746 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
747 selection.collapse_to(cursor, new_goal)
748 });
749 }
750
751 pub fn maybe_move_cursors_with(
752 &mut self,
753 mut update_cursor_position: impl FnMut(
754 &DisplaySnapshot,
755 DisplayPoint,
756 SelectionGoal,
757 ) -> Option<(DisplayPoint, SelectionGoal)>,
758 ) {
759 self.move_cursors_with(|map, point, goal| {
760 update_cursor_position(map, point, goal).unwrap_or((point, goal))
761 })
762 }
763
764 pub fn replace_cursors_with(
765 &mut self,
766 find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
767 ) {
768 let display_map = self.display_map();
769 let new_selections = find_replacement_cursors(&display_map)
770 .into_iter()
771 .map(|cursor| {
772 let cursor_point = cursor.to_point(&display_map);
773 Selection {
774 id: post_inc(&mut self.collection.next_selection_id),
775 start: cursor_point,
776 end: cursor_point,
777 reversed: false,
778 goal: SelectionGoal::None,
779 }
780 })
781 .collect();
782 self.select(new_selections);
783 }
784
785 /// Compute new ranges for any selections that were located in excerpts that have
786 /// since been removed.
787 ///
788 /// Returns a `HashMap` indicating which selections whose former head position
789 /// was no longer present. The keys of the map are selection ids. The values are
790 /// the id of the new excerpt where the head of the selection has been moved.
791 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
792 let mut pending = self.collection.pending.take();
793 let mut selections_with_lost_position = HashMap::default();
794
795 let anchors_with_status = {
796 let buffer = self.buffer();
797 let disjoint_anchors = self
798 .disjoint
799 .iter()
800 .flat_map(|selection| [&selection.start, &selection.end]);
801 buffer.refresh_anchors(disjoint_anchors)
802 };
803 let adjusted_disjoint: Vec<_> = anchors_with_status
804 .chunks(2)
805 .map(|selection_anchors| {
806 let (anchor_ix, start, kept_start) = selection_anchors[0];
807 let (_, end, kept_end) = selection_anchors[1];
808 let selection = &self.disjoint[anchor_ix / 2];
809 let kept_head = if selection.reversed {
810 kept_start
811 } else {
812 kept_end
813 };
814 if !kept_head {
815 selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
816 }
817
818 Selection {
819 id: selection.id,
820 start,
821 end,
822 reversed: selection.reversed,
823 goal: selection.goal,
824 }
825 })
826 .collect();
827
828 if !adjusted_disjoint.is_empty() {
829 let map = self.display_map();
830 let resolved_selections = resolve_selections(adjusted_disjoint.iter(), &map).collect();
831 self.select::<usize>(resolved_selections);
832 }
833
834 if let Some(pending) = pending.as_mut() {
835 let buffer = self.buffer();
836 let anchors =
837 buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
838 let (_, start, kept_start) = anchors[0];
839 let (_, end, kept_end) = anchors[1];
840 let kept_head = if pending.selection.reversed {
841 kept_start
842 } else {
843 kept_end
844 };
845 if !kept_head {
846 selections_with_lost_position
847 .insert(pending.selection.id, pending.selection.head().excerpt_id);
848 }
849
850 pending.selection.start = start;
851 pending.selection.end = end;
852 }
853 self.collection.pending = pending;
854 self.selections_changed = true;
855
856 selections_with_lost_position
857 }
858}
859
860impl<'a> Deref for MutableSelectionsCollection<'a> {
861 type Target = SelectionsCollection;
862 fn deref(&self) -> &Self::Target {
863 self.collection
864 }
865}
866
867impl<'a> DerefMut for MutableSelectionsCollection<'a> {
868 fn deref_mut(&mut self) -> &mut Self::Target {
869 self.collection
870 }
871}
872
873// Panics if passed selections are not in order
874fn resolve_selections_display<'a>(
875 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
876 map: &'a DisplaySnapshot,
877) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
878 let (to_summarize, selections) = selections.into_iter().tee();
879 let mut summaries = map
880 .buffer_snapshot
881 .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
882 .into_iter();
883 let mut selections = selections
884 .map(move |s| {
885 let start = summaries.next().unwrap();
886 let end = summaries.next().unwrap();
887
888 let display_start = map.point_to_display_point(start, Bias::Left);
889 let display_end = if start == end {
890 map.point_to_display_point(end, Bias::Right)
891 } else {
892 map.point_to_display_point(end, Bias::Left)
893 };
894
895 Selection {
896 id: s.id,
897 start: display_start,
898 end: display_end,
899 reversed: s.reversed,
900 goal: s.goal,
901 }
902 })
903 .peekable();
904 iter::from_fn(move || {
905 let mut selection = selections.next()?;
906 while let Some(next_selection) = selections.peek() {
907 if selection.end >= next_selection.start {
908 selection.end = cmp::max(selection.end, next_selection.end);
909 selections.next();
910 } else {
911 break;
912 }
913 }
914 Some(selection)
915 })
916}
917
918// Panics if passed selections are not in order
919pub(crate) fn resolve_selections<'a, D, I>(
920 selections: I,
921 map: &'a DisplaySnapshot,
922) -> impl 'a + Iterator<Item = Selection<D>>
923where
924 D: TextDimension + Clone + Ord + Sub<D, Output = D>,
925 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
926{
927 let (to_convert, selections) = resolve_selections_display(selections, map).tee();
928 let mut converted_endpoints =
929 map.buffer_snapshot
930 .dimensions_from_points::<D>(to_convert.flat_map(|s| {
931 let start = map.display_point_to_point(s.start, Bias::Left);
932 let end = map.display_point_to_point(s.end, Bias::Right);
933 [start, end]
934 }));
935 selections.map(move |s| {
936 let start = converted_endpoints.next().unwrap();
937 let end = converted_endpoints.next().unwrap();
938 Selection {
939 id: s.id,
940 start,
941 end,
942 reversed: s.reversed,
943 goal: s.goal,
944 }
945 })
946}