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 pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
327 &self,
328 cx: &mut AppContext,
329 ) -> Vec<Range<D>> {
330 self.all::<D>(cx)
331 .iter()
332 .map(|s| {
333 if s.reversed {
334 s.end..s.start
335 } else {
336 s.start..s.end
337 }
338 })
339 .collect()
340 }
341
342 #[cfg(any(test, feature = "test-support"))]
343 pub fn display_ranges(&self, cx: &mut AppContext) -> Vec<Range<DisplayPoint>> {
344 let display_map = self.display_map(cx);
345 self.disjoint_anchors()
346 .iter()
347 .chain(self.pending_anchor().as_ref())
348 .map(|s| {
349 if s.reversed {
350 s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
351 } else {
352 s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
353 }
354 })
355 .collect()
356 }
357
358 pub fn build_columnar_selection(
359 &mut self,
360 display_map: &DisplaySnapshot,
361 row: DisplayRow,
362 positions: &Range<Pixels>,
363 reversed: bool,
364 text_layout_details: &TextLayoutDetails,
365 ) -> Option<Selection<Point>> {
366 let is_empty = positions.start == positions.end;
367 let line_len = display_map.line_len(row);
368
369 let line = display_map.layout_row(row, text_layout_details);
370
371 let start_col = line.closest_index_for_x(positions.start) as u32;
372 if start_col < line_len || (is_empty && positions.start == line.width) {
373 let start = DisplayPoint::new(row, start_col);
374 let end_col = line.closest_index_for_x(positions.end) as u32;
375 let end = DisplayPoint::new(row, end_col);
376
377 Some(Selection {
378 id: post_inc(&mut self.next_selection_id),
379 start: start.to_point(display_map),
380 end: end.to_point(display_map),
381 reversed,
382 goal: SelectionGoal::HorizontalRange {
383 start: positions.start.into(),
384 end: positions.end.into(),
385 },
386 })
387 } else {
388 None
389 }
390 }
391
392 pub fn change_with<R>(
393 &mut self,
394 cx: &mut AppContext,
395 change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
396 ) -> (bool, R) {
397 let mut mutable_collection = MutableSelectionsCollection {
398 collection: self,
399 selections_changed: false,
400 cx,
401 };
402
403 let result = change(&mut mutable_collection);
404 assert!(
405 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
406 "There must be at least one selection"
407 );
408 (mutable_collection.selections_changed, result)
409 }
410}
411
412pub struct MutableSelectionsCollection<'a> {
413 collection: &'a mut SelectionsCollection,
414 selections_changed: bool,
415 cx: &'a mut AppContext,
416}
417
418impl<'a> MutableSelectionsCollection<'a> {
419 pub fn display_map(&mut self) -> DisplaySnapshot {
420 self.collection.display_map(self.cx)
421 }
422
423 pub fn buffer(&self) -> Ref<MultiBufferSnapshot> {
424 self.collection.buffer(self.cx)
425 }
426
427 pub fn clear_disjoint(&mut self) {
428 self.collection.disjoint = Arc::default();
429 }
430
431 pub fn delete(&mut self, selection_id: usize) {
432 let mut changed = false;
433 self.collection.disjoint = self
434 .disjoint
435 .iter()
436 .filter(|selection| {
437 let found = selection.id == selection_id;
438 changed |= found;
439 !found
440 })
441 .cloned()
442 .collect();
443
444 self.selections_changed |= changed;
445 }
446
447 pub fn clear_pending(&mut self) {
448 if self.collection.pending.is_some() {
449 self.collection.pending = None;
450 self.selections_changed = true;
451 }
452 }
453
454 pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
455 self.collection.pending = Some(PendingSelection {
456 selection: Selection {
457 id: post_inc(&mut self.collection.next_selection_id),
458 start: range.start,
459 end: range.end,
460 reversed: false,
461 goal: SelectionGoal::None,
462 },
463 mode,
464 });
465 self.selections_changed = true;
466 }
467
468 pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
469 self.collection.pending = Some(PendingSelection { selection, mode });
470 self.selections_changed = true;
471 }
472
473 pub fn try_cancel(&mut self) -> bool {
474 if let Some(pending) = self.collection.pending.take() {
475 if self.disjoint.is_empty() {
476 self.collection.disjoint = Arc::from([pending.selection]);
477 }
478 self.selections_changed = true;
479 return true;
480 }
481
482 let mut oldest = self.oldest_anchor().clone();
483 if self.count() > 1 {
484 self.collection.disjoint = Arc::from([oldest]);
485 self.selections_changed = true;
486 return true;
487 }
488
489 if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
490 let head = oldest.head();
491 oldest.start = head;
492 oldest.end = head;
493 self.collection.disjoint = Arc::from([oldest]);
494 self.selections_changed = true;
495 return true;
496 }
497
498 false
499 }
500
501 pub fn insert_range<T>(&mut self, range: Range<T>)
502 where
503 T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
504 {
505 let mut selections = self.collection.all(self.cx);
506 let mut start = range.start.to_offset(&self.buffer());
507 let mut end = range.end.to_offset(&self.buffer());
508 let reversed = if start > end {
509 mem::swap(&mut start, &mut end);
510 true
511 } else {
512 false
513 };
514 selections.push(Selection {
515 id: post_inc(&mut self.collection.next_selection_id),
516 start,
517 end,
518 reversed,
519 goal: SelectionGoal::None,
520 });
521 self.select(selections);
522 }
523
524 pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
525 where
526 T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
527 {
528 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
529 selections.sort_unstable_by_key(|s| s.start);
530 // Merge overlapping selections.
531 let mut i = 1;
532 while i < selections.len() {
533 if selections[i - 1].end >= selections[i].start {
534 let removed = selections.remove(i);
535 if removed.start < selections[i - 1].start {
536 selections[i - 1].start = removed.start;
537 }
538 if removed.end > selections[i - 1].end {
539 selections[i - 1].end = removed.end;
540 }
541 } else {
542 i += 1;
543 }
544 }
545
546 self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
547 let end_bias = if selection.end > selection.start {
548 Bias::Left
549 } else {
550 Bias::Right
551 };
552 Selection {
553 id: selection.id,
554 start: buffer.anchor_after(selection.start),
555 end: buffer.anchor_at(selection.end, end_bias),
556 reversed: selection.reversed,
557 goal: selection.goal,
558 }
559 }));
560
561 self.collection.pending = None;
562 self.selections_changed = true;
563 }
564
565 pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
566 let map = self.display_map();
567 let resolved_selections =
568 resolve_selections::<usize, _>(&selections, &map).collect::<Vec<_>>();
569 self.select(resolved_selections);
570 }
571
572 pub fn select_ranges<I, T>(&mut self, ranges: I)
573 where
574 I: IntoIterator<Item = Range<T>>,
575 T: ToOffset,
576 {
577 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
578 let ranges = ranges
579 .into_iter()
580 .map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer));
581 self.select_offset_ranges(ranges);
582 }
583
584 fn select_offset_ranges<I>(&mut self, ranges: I)
585 where
586 I: IntoIterator<Item = Range<usize>>,
587 {
588 let selections = ranges
589 .into_iter()
590 .map(|range| {
591 let mut start = range.start;
592 let mut end = range.end;
593 let reversed = if start > end {
594 mem::swap(&mut start, &mut end);
595 true
596 } else {
597 false
598 };
599 Selection {
600 id: post_inc(&mut self.collection.next_selection_id),
601 start,
602 end,
603 reversed,
604 goal: SelectionGoal::None,
605 }
606 })
607 .collect::<Vec<_>>();
608
609 self.select(selections)
610 }
611
612 pub fn select_anchor_ranges<I>(&mut self, ranges: I)
613 where
614 I: IntoIterator<Item = Range<Anchor>>,
615 {
616 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
617 let selections = ranges
618 .into_iter()
619 .map(|range| {
620 let mut start = range.start;
621 let mut end = range.end;
622 let reversed = if start.cmp(&end, &buffer).is_gt() {
623 mem::swap(&mut start, &mut end);
624 true
625 } else {
626 false
627 };
628 Selection {
629 id: post_inc(&mut self.collection.next_selection_id),
630 start,
631 end,
632 reversed,
633 goal: SelectionGoal::None,
634 }
635 })
636 .collect::<Vec<_>>();
637 self.select_anchors(selections)
638 }
639
640 pub fn new_selection_id(&mut self) -> usize {
641 post_inc(&mut self.next_selection_id)
642 }
643
644 pub fn select_display_ranges<T>(&mut self, ranges: T)
645 where
646 T: IntoIterator<Item = Range<DisplayPoint>>,
647 {
648 let display_map = self.display_map();
649 let selections = ranges
650 .into_iter()
651 .map(|range| {
652 let mut start = range.start;
653 let mut end = range.end;
654 let reversed = if start > end {
655 mem::swap(&mut start, &mut end);
656 true
657 } else {
658 false
659 };
660 Selection {
661 id: post_inc(&mut self.collection.next_selection_id),
662 start: start.to_point(&display_map),
663 end: end.to_point(&display_map),
664 reversed,
665 goal: SelectionGoal::None,
666 }
667 })
668 .collect();
669 self.select(selections);
670 }
671
672 pub fn move_with(
673 &mut self,
674 mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
675 ) {
676 let mut changed = false;
677 let display_map = self.display_map();
678 let (_, selections) = self.collection.all_display(self.cx);
679 let selections = selections
680 .into_iter()
681 .map(|selection| {
682 let mut moved_selection = selection.clone();
683 move_selection(&display_map, &mut moved_selection);
684 if selection != moved_selection {
685 changed = true;
686 }
687 moved_selection.map(|display_point| display_point.to_point(&display_map))
688 })
689 .collect();
690
691 if changed {
692 self.select(selections)
693 }
694 }
695
696 pub fn move_offsets_with(
697 &mut self,
698 mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
699 ) {
700 let mut changed = false;
701 let snapshot = self.buffer().clone();
702 let selections = self
703 .collection
704 .all::<usize>(self.cx)
705 .into_iter()
706 .map(|selection| {
707 let mut moved_selection = selection.clone();
708 move_selection(&snapshot, &mut moved_selection);
709 if selection != moved_selection {
710 changed = true;
711 }
712 moved_selection
713 })
714 .collect();
715 drop(snapshot);
716
717 if changed {
718 self.select(selections)
719 }
720 }
721
722 pub fn move_heads_with(
723 &mut self,
724 mut update_head: impl FnMut(
725 &DisplaySnapshot,
726 DisplayPoint,
727 SelectionGoal,
728 ) -> (DisplayPoint, SelectionGoal),
729 ) {
730 self.move_with(|map, selection| {
731 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
732 selection.set_head(new_head, new_goal);
733 });
734 }
735
736 pub fn move_cursors_with(
737 &mut self,
738 mut update_cursor_position: impl FnMut(
739 &DisplaySnapshot,
740 DisplayPoint,
741 SelectionGoal,
742 ) -> (DisplayPoint, SelectionGoal),
743 ) {
744 self.move_with(|map, selection| {
745 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
746 selection.collapse_to(cursor, new_goal)
747 });
748 }
749
750 pub fn maybe_move_cursors_with(
751 &mut self,
752 mut update_cursor_position: impl FnMut(
753 &DisplaySnapshot,
754 DisplayPoint,
755 SelectionGoal,
756 ) -> Option<(DisplayPoint, SelectionGoal)>,
757 ) {
758 self.move_cursors_with(|map, point, goal| {
759 update_cursor_position(map, point, goal).unwrap_or((point, goal))
760 })
761 }
762
763 pub fn replace_cursors_with(
764 &mut self,
765 find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
766 ) {
767 let display_map = self.display_map();
768 let new_selections = find_replacement_cursors(&display_map)
769 .into_iter()
770 .map(|cursor| {
771 let cursor_point = cursor.to_point(&display_map);
772 Selection {
773 id: post_inc(&mut self.collection.next_selection_id),
774 start: cursor_point,
775 end: cursor_point,
776 reversed: false,
777 goal: SelectionGoal::None,
778 }
779 })
780 .collect();
781 self.select(new_selections);
782 }
783
784 /// Compute new ranges for any selections that were located in excerpts that have
785 /// since been removed.
786 ///
787 /// Returns a `HashMap` indicating which selections whose former head position
788 /// was no longer present. The keys of the map are selection ids. The values are
789 /// the id of the new excerpt where the head of the selection has been moved.
790 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
791 let mut pending = self.collection.pending.take();
792 let mut selections_with_lost_position = HashMap::default();
793
794 let anchors_with_status = {
795 let buffer = self.buffer();
796 let disjoint_anchors = self
797 .disjoint
798 .iter()
799 .flat_map(|selection| [&selection.start, &selection.end]);
800 buffer.refresh_anchors(disjoint_anchors)
801 };
802 let adjusted_disjoint: Vec<_> = anchors_with_status
803 .chunks(2)
804 .map(|selection_anchors| {
805 let (anchor_ix, start, kept_start) = selection_anchors[0];
806 let (_, end, kept_end) = selection_anchors[1];
807 let selection = &self.disjoint[anchor_ix / 2];
808 let kept_head = if selection.reversed {
809 kept_start
810 } else {
811 kept_end
812 };
813 if !kept_head {
814 selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
815 }
816
817 Selection {
818 id: selection.id,
819 start,
820 end,
821 reversed: selection.reversed,
822 goal: selection.goal,
823 }
824 })
825 .collect();
826
827 if !adjusted_disjoint.is_empty() {
828 let map = self.display_map();
829 let resolved_selections = resolve_selections(adjusted_disjoint.iter(), &map).collect();
830 self.select::<usize>(resolved_selections);
831 }
832
833 if let Some(pending) = pending.as_mut() {
834 let buffer = self.buffer();
835 let anchors =
836 buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
837 let (_, start, kept_start) = anchors[0];
838 let (_, end, kept_end) = anchors[1];
839 let kept_head = if pending.selection.reversed {
840 kept_start
841 } else {
842 kept_end
843 };
844 if !kept_head {
845 selections_with_lost_position
846 .insert(pending.selection.id, pending.selection.head().excerpt_id);
847 }
848
849 pending.selection.start = start;
850 pending.selection.end = end;
851 }
852 self.collection.pending = pending;
853 self.selections_changed = true;
854
855 selections_with_lost_position
856 }
857}
858
859impl<'a> Deref for MutableSelectionsCollection<'a> {
860 type Target = SelectionsCollection;
861 fn deref(&self) -> &Self::Target {
862 self.collection
863 }
864}
865
866impl<'a> DerefMut for MutableSelectionsCollection<'a> {
867 fn deref_mut(&mut self) -> &mut Self::Target {
868 self.collection
869 }
870}
871
872// Panics if passed selections are not in order
873fn resolve_selections_display<'a>(
874 selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
875 map: &'a DisplaySnapshot,
876) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
877 let (to_summarize, selections) = selections.into_iter().tee();
878 let mut summaries = map
879 .buffer_snapshot
880 .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
881 .into_iter();
882 let mut selections = selections
883 .map(move |s| {
884 let start = summaries.next().unwrap();
885 let end = summaries.next().unwrap();
886
887 let display_start = map.point_to_display_point(start, Bias::Left);
888 let display_end = if start == end {
889 map.point_to_display_point(end, Bias::Right)
890 } else {
891 map.point_to_display_point(end, Bias::Left)
892 };
893
894 Selection {
895 id: s.id,
896 start: display_start,
897 end: display_end,
898 reversed: s.reversed,
899 goal: s.goal,
900 }
901 })
902 .peekable();
903 iter::from_fn(move || {
904 let mut selection = selections.next()?;
905 while let Some(next_selection) = selections.peek() {
906 if selection.end >= next_selection.start {
907 selection.end = cmp::max(selection.end, next_selection.end);
908 selections.next();
909 } else {
910 break;
911 }
912 }
913 Some(selection)
914 })
915}
916
917// Panics if passed selections are not in order
918pub(crate) fn resolve_selections<'a, D, I>(
919 selections: I,
920 map: &'a DisplaySnapshot,
921) -> impl 'a + Iterator<Item = Selection<D>>
922where
923 D: TextDimension + Ord + Sub<D, Output = D>,
924 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
925{
926 let (to_convert, selections) = resolve_selections_display(selections, map).tee();
927 let mut converted_endpoints =
928 map.buffer_snapshot
929 .dimensions_from_points::<D>(to_convert.flat_map(|s| {
930 let start = map.display_point_to_point(s.start, Bias::Left);
931 let end = map.display_point_to_point(s.end, Bias::Right);
932 [start, end]
933 }));
934 selections.map(move |s| {
935 let start = converted_endpoints.next().unwrap();
936 let end = converted_endpoints.next().unwrap();
937 Selection {
938 id: s.id,
939 start,
940 end,
941 reversed: s.reversed,
942 goal: s.goal,
943 }
944 })
945}