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