1use std::{
2 cell::Ref,
3 cmp, iter, mem,
4 ops::{Deref, Range, Sub},
5 sync::Arc,
6};
7
8use collections::HashMap;
9use gpui::{AppContext, ModelHandle, MutableAppContext};
10use itertools::Itertools;
11use language::{rope::TextDimension, Bias, Point, Selection, SelectionGoal, ToPoint};
12use util::post_inc;
13
14use crate::{
15 display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
16 Anchor, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset,
17};
18
19#[derive(Clone)]
20pub struct PendingSelection {
21 pub selection: Selection<Anchor>,
22 pub mode: SelectMode,
23}
24
25#[derive(Clone)]
26pub struct SelectionsCollection {
27 display_map: ModelHandle<DisplayMap>,
28 buffer: ModelHandle<MultiBuffer>,
29 pub next_selection_id: usize,
30 disjoint: Arc<[Selection<Anchor>]>,
31 pending: Option<PendingSelection>,
32}
33
34impl SelectionsCollection {
35 pub fn new(display_map: ModelHandle<DisplayMap>, buffer: ModelHandle<MultiBuffer>) -> Self {
36 Self {
37 display_map,
38 buffer,
39 next_selection_id: 1,
40 disjoint: Arc::from([]),
41 pending: Some(PendingSelection {
42 selection: Selection {
43 id: 0,
44 start: Anchor::min(),
45 end: Anchor::min(),
46 reversed: false,
47 goal: SelectionGoal::None,
48 },
49 mode: SelectMode::Character,
50 }),
51 }
52 }
53
54 fn display_map(&self, cx: &mut MutableAppContext) -> DisplaySnapshot {
55 self.display_map.update(cx, |map, cx| map.snapshot(cx))
56 }
57
58 fn buffer<'a>(&self, cx: &'a AppContext) -> Ref<'a, MultiBufferSnapshot> {
59 self.buffer.read(cx).read(cx)
60 }
61
62 pub fn count<'a>(&self) -> usize {
63 let mut count = self.disjoint.len();
64 if self.pending.is_some() {
65 count += 1;
66 }
67 count
68 }
69
70 pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> {
71 self.disjoint.clone()
72 }
73
74 pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
75 self.pending
76 .as_ref()
77 .map(|pending| pending.selection.clone())
78 }
79
80 pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
81 &self,
82 cx: &AppContext,
83 ) -> Option<Selection<D>> {
84 self.pending_anchor()
85 .as_ref()
86 .map(|pending| pending.map(|p| p.summary::<D>(&self.buffer(cx))))
87 }
88
89 pub fn pending_mode(&self) -> Option<SelectMode> {
90 self.pending.as_ref().map(|pending| pending.mode.clone())
91 }
92
93 pub fn all<'a, D>(&self, cx: &AppContext) -> Vec<Selection<D>>
94 where
95 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
96 {
97 let disjoint_anchors = &self.disjoint;
98 let mut disjoint =
99 resolve_multiple::<D, _>(disjoint_anchors.iter(), &self.buffer(cx)).peekable();
100
101 let mut pending_opt = self.pending::<D>(cx);
102
103 iter::from_fn(move || {
104 if let Some(pending) = pending_opt.as_mut() {
105 while let Some(next_selection) = disjoint.peek() {
106 if pending.start <= next_selection.end && pending.end >= next_selection.start {
107 let next_selection = disjoint.next().unwrap();
108 if next_selection.start < pending.start {
109 pending.start = next_selection.start;
110 }
111 if next_selection.end > pending.end {
112 pending.end = next_selection.end;
113 }
114 } else if next_selection.end < pending.start {
115 return disjoint.next();
116 } else {
117 break;
118 }
119 }
120
121 pending_opt.take()
122 } else {
123 disjoint.next()
124 }
125 })
126 .collect()
127 }
128
129 pub fn disjoint_in_range<'a, D>(
130 &self,
131 range: Range<Anchor>,
132 cx: &AppContext,
133 ) -> Vec<Selection<D>>
134 where
135 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
136 {
137 let buffer = self.buffer(cx);
138 let start_ix = match self
139 .disjoint
140 .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
141 {
142 Ok(ix) | Err(ix) => ix,
143 };
144 let end_ix = match self
145 .disjoint
146 .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
147 {
148 Ok(ix) => ix + 1,
149 Err(ix) => ix,
150 };
151 resolve_multiple(&self.disjoint[start_ix..end_ix], &buffer).collect()
152 }
153
154 pub fn all_display(
155 &mut self,
156 cx: &mut MutableAppContext,
157 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
158 let display_map = self.display_map(cx);
159 let selections = self
160 .all::<Point>(cx)
161 .into_iter()
162 .map(|selection| selection.map(|point| point.to_display_point(&display_map)))
163 .collect();
164 (display_map, selections)
165 }
166
167 pub fn newest_anchor(&self) -> &Selection<Anchor> {
168 self.pending
169 .as_ref()
170 .map(|s| &s.selection)
171 .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
172 .unwrap()
173 }
174
175 pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
176 &self,
177 cx: &AppContext,
178 ) -> Selection<D> {
179 resolve(self.newest_anchor(), &self.buffer(cx))
180 }
181
182 pub fn oldest_anchor(&self) -> &Selection<Anchor> {
183 self.disjoint
184 .iter()
185 .min_by_key(|s| s.id)
186 .or_else(|| self.pending.as_ref().map(|p| &p.selection))
187 .unwrap()
188 }
189
190 pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
191 &self,
192 cx: &AppContext,
193 ) -> Selection<D> {
194 resolve(self.oldest_anchor(), &self.buffer(cx))
195 }
196
197 pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
198 &self,
199 cx: &AppContext,
200 ) -> Selection<D> {
201 self.all(cx).first().unwrap().clone()
202 }
203
204 pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
205 &self,
206 cx: &AppContext,
207 ) -> Selection<D> {
208 self.all(cx).last().unwrap().clone()
209 }
210
211 #[cfg(any(test, feature = "test-support"))]
212 pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
213 &self,
214 cx: &AppContext,
215 ) -> Vec<Range<D>> {
216 self.all::<D>(cx)
217 .iter()
218 .map(|s| {
219 if s.reversed {
220 s.end.clone()..s.start.clone()
221 } else {
222 s.start.clone()..s.end.clone()
223 }
224 })
225 .collect()
226 }
227
228 #[cfg(any(test, feature = "test-support"))]
229 pub fn display_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
230 let display_map = self.display_map(cx);
231 self.disjoint_anchors()
232 .iter()
233 .chain(self.pending_anchor().as_ref())
234 .map(|s| {
235 if s.reversed {
236 s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
237 } else {
238 s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
239 }
240 })
241 .collect()
242 }
243
244 pub fn build_columnar_selection(
245 &mut self,
246 display_map: &DisplaySnapshot,
247 row: u32,
248 columns: &Range<u32>,
249 reversed: bool,
250 ) -> Option<Selection<Point>> {
251 let is_empty = columns.start == columns.end;
252 let line_len = display_map.line_len(row);
253 if columns.start < line_len || (is_empty && columns.start == line_len) {
254 let start = DisplayPoint::new(row, columns.start);
255 let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
256
257 Some(Selection {
258 id: post_inc(&mut self.next_selection_id),
259 start: start.to_point(display_map),
260 end: end.to_point(display_map),
261 reversed,
262 goal: SelectionGoal::ColumnRange {
263 start: columns.start,
264 end: columns.end,
265 },
266 })
267 } else {
268 None
269 }
270 }
271
272 pub(crate) fn change_with<R>(
273 &mut self,
274 cx: &mut MutableAppContext,
275 change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
276 ) -> R {
277 let mut mutable_collection = MutableSelectionsCollection {
278 collection: self,
279 cx,
280 };
281
282 let result = change(&mut mutable_collection);
283 assert!(
284 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
285 "There must be at least one selection"
286 );
287 result
288 }
289}
290
291pub struct MutableSelectionsCollection<'a> {
292 collection: &'a mut SelectionsCollection,
293 cx: &'a mut MutableAppContext,
294}
295
296impl<'a> MutableSelectionsCollection<'a> {
297 fn display_map(&mut self) -> DisplaySnapshot {
298 self.collection.display_map(self.cx)
299 }
300
301 fn buffer(&self) -> Ref<MultiBufferSnapshot> {
302 self.collection.buffer(self.cx)
303 }
304
305 pub fn clear_disjoint(&mut self) {
306 self.collection.disjoint = Arc::from([]);
307 }
308
309 pub fn delete(&mut self, selection_id: usize) {
310 self.collection.disjoint = self
311 .disjoint
312 .into_iter()
313 .filter(|selection| selection.id != selection_id)
314 .cloned()
315 .collect();
316 }
317
318 pub fn clear_pending(&mut self) {
319 self.collection.pending = None;
320 }
321
322 pub fn set_pending_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
323 self.collection.pending = Some(PendingSelection {
324 selection: Selection {
325 id: post_inc(&mut self.collection.next_selection_id),
326 start: range.start,
327 end: range.end,
328 reversed: false,
329 goal: SelectionGoal::None,
330 },
331 mode,
332 })
333 }
334
335 pub fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
336 self.collection.pending = Some(PendingSelection { selection, mode });
337 }
338
339 pub fn try_cancel(&mut self) -> bool {
340 if let Some(pending) = self.collection.pending.take() {
341 if self.disjoint.is_empty() {
342 self.collection.disjoint = Arc::from([pending.selection]);
343 }
344 return true;
345 }
346
347 let mut oldest = self.oldest_anchor().clone();
348 if self.count() > 1 {
349 self.collection.disjoint = Arc::from([oldest]);
350 return true;
351 }
352
353 if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
354 let head = oldest.head();
355 oldest.start = head.clone();
356 oldest.end = head;
357 self.collection.disjoint = Arc::from([oldest]);
358 return true;
359 }
360
361 return false;
362 }
363
364 pub fn reset_biases(&mut self) {
365 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
366 self.collection.disjoint = self
367 .collection
368 .disjoint
369 .into_iter()
370 .cloned()
371 .map(|selection| reset_biases(selection, &buffer))
372 .collect();
373
374 if let Some(pending) = self.collection.pending.as_mut() {
375 pending.selection = reset_biases(pending.selection.clone(), &buffer);
376 }
377 }
378
379 pub fn insert_range<T>(&mut self, range: Range<T>)
380 where
381 T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
382 {
383 let mut selections = self.all(self.cx);
384 let mut start = range.start.to_offset(&self.buffer());
385 let mut end = range.end.to_offset(&self.buffer());
386 let reversed = if start > end {
387 mem::swap(&mut start, &mut end);
388 true
389 } else {
390 false
391 };
392 selections.push(Selection {
393 id: post_inc(&mut self.collection.next_selection_id),
394 start,
395 end,
396 reversed,
397 goal: SelectionGoal::None,
398 });
399 self.select(selections);
400 }
401
402 pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
403 where
404 T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
405 {
406 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
407 selections.sort_unstable_by_key(|s| s.start);
408 // Merge overlapping selections.
409 let mut i = 1;
410 while i < selections.len() {
411 if selections[i - 1].end >= selections[i].start {
412 let removed = selections.remove(i);
413 if removed.start < selections[i - 1].start {
414 selections[i - 1].start = removed.start;
415 }
416 if removed.end > selections[i - 1].end {
417 selections[i - 1].end = removed.end;
418 }
419 } else {
420 i += 1;
421 }
422 }
423
424 self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
425 let end_bias = if selection.end > selection.start {
426 Bias::Left
427 } else {
428 Bias::Right
429 };
430 Selection {
431 id: selection.id,
432 start: buffer.anchor_after(selection.start),
433 end: buffer.anchor_at(selection.end, end_bias),
434 reversed: selection.reversed,
435 goal: selection.goal,
436 }
437 }));
438
439 self.collection.pending = None;
440 }
441
442 pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
443 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
444 let resolved_selections =
445 resolve_multiple::<usize, _>(&selections, &buffer).collect::<Vec<_>>();
446 self.select(resolved_selections);
447 }
448
449 pub fn select_ranges<I, T>(&mut self, ranges: I)
450 where
451 I: IntoIterator<Item = Range<T>>,
452 T: ToOffset,
453 {
454 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
455 let selections = ranges
456 .into_iter()
457 .map(|range| {
458 let mut start = range.start.to_offset(&buffer);
459 let mut end = range.end.to_offset(&buffer);
460 let reversed = if start > end {
461 mem::swap(&mut start, &mut end);
462 true
463 } else {
464 false
465 };
466 Selection {
467 id: post_inc(&mut self.collection.next_selection_id),
468 start,
469 end,
470 reversed,
471 goal: SelectionGoal::None,
472 }
473 })
474 .collect::<Vec<_>>();
475
476 self.select(selections)
477 }
478
479 pub fn select_anchor_ranges<I: IntoIterator<Item = Range<Anchor>>>(&mut self, ranges: I) {
480 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
481 let selections = ranges
482 .into_iter()
483 .map(|range| {
484 let mut start = range.start;
485 let mut end = range.end;
486 let reversed = if start.cmp(&end, &buffer).is_gt() {
487 mem::swap(&mut start, &mut end);
488 true
489 } else {
490 false
491 };
492 Selection {
493 id: post_inc(&mut self.collection.next_selection_id),
494 start,
495 end,
496 reversed,
497 goal: SelectionGoal::None,
498 }
499 })
500 .collect::<Vec<_>>();
501
502 self.select_anchors(selections)
503 }
504
505 #[cfg(any(test, feature = "test-support"))]
506 pub fn select_display_ranges<T>(&mut self, ranges: T)
507 where
508 T: IntoIterator<Item = Range<DisplayPoint>>,
509 {
510 let display_map = self.display_map();
511 let selections = ranges
512 .into_iter()
513 .map(|range| {
514 let mut start = range.start;
515 let mut end = range.end;
516 let reversed = if start > end {
517 mem::swap(&mut start, &mut end);
518 true
519 } else {
520 false
521 };
522 Selection {
523 id: post_inc(&mut self.collection.next_selection_id),
524 start: start.to_point(&display_map),
525 end: end.to_point(&display_map),
526 reversed,
527 goal: SelectionGoal::None,
528 }
529 })
530 .collect();
531 self.select(selections);
532 }
533
534 pub fn move_with(
535 &mut self,
536 mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
537 ) {
538 let display_map = self.display_map();
539 let selections = self
540 .all::<Point>(self.cx)
541 .into_iter()
542 .map(|selection| {
543 let mut selection = selection.map(|point| point.to_display_point(&display_map));
544 move_selection(&display_map, &mut selection);
545 selection.map(|display_point| display_point.to_point(&display_map))
546 })
547 .collect();
548
549 self.select(selections)
550 }
551
552 pub fn move_heads_with(
553 &mut self,
554 mut update_head: impl FnMut(
555 &DisplaySnapshot,
556 DisplayPoint,
557 SelectionGoal,
558 ) -> (DisplayPoint, SelectionGoal),
559 ) {
560 self.move_with(|map, selection| {
561 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
562 selection.set_head(new_head, new_goal);
563 });
564 }
565
566 pub fn move_cursors_with(
567 &mut self,
568 mut update_cursor_position: impl FnMut(
569 &DisplaySnapshot,
570 DisplayPoint,
571 SelectionGoal,
572 ) -> (DisplayPoint, SelectionGoal),
573 ) {
574 self.move_with(|map, selection| {
575 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
576 selection.collapse_to(cursor, new_goal)
577 });
578 }
579
580 pub fn replace_cursors_with(
581 &mut self,
582 mut find_replacement_cursors: impl FnMut(&DisplaySnapshot) -> Vec<DisplayPoint>,
583 ) {
584 let display_map = self.display_map();
585 let new_selections = find_replacement_cursors(&display_map)
586 .into_iter()
587 .map(|cursor| {
588 let cursor_point = cursor.to_point(&display_map);
589 Selection {
590 id: post_inc(&mut self.collection.next_selection_id),
591 start: cursor_point,
592 end: cursor_point,
593 reversed: false,
594 goal: SelectionGoal::None,
595 }
596 })
597 .collect();
598 self.select(new_selections);
599 }
600
601 /// Compute new ranges for any selections that were located in excerpts that have
602 /// since been removed.
603 ///
604 /// Returns a `HashMap` indicating which selections whose former head position
605 /// was no longer present. The keys of the map are selection ids. The values are
606 /// the id of the new excerpt where the head of the selection has been moved.
607 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
608 let mut pending = self.collection.pending.take();
609 let mut selections_with_lost_position = HashMap::default();
610
611 let anchors_with_status = {
612 let buffer = self.buffer();
613 let disjoint_anchors = self
614 .disjoint
615 .iter()
616 .flat_map(|selection| [&selection.start, &selection.end]);
617 buffer.refresh_anchors(disjoint_anchors)
618 };
619 let adjusted_disjoint: Vec<_> = anchors_with_status
620 .chunks(2)
621 .map(|selection_anchors| {
622 let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
623 let (_, end, kept_end) = selection_anchors[1].clone();
624 let selection = &self.disjoint[anchor_ix / 2];
625 let kept_head = if selection.reversed {
626 kept_start
627 } else {
628 kept_end
629 };
630 if !kept_head {
631 selections_with_lost_position
632 .insert(selection.id, selection.head().excerpt_id.clone());
633 }
634
635 Selection {
636 id: selection.id,
637 start,
638 end,
639 reversed: selection.reversed,
640 goal: selection.goal,
641 }
642 })
643 .collect();
644
645 if !adjusted_disjoint.is_empty() {
646 let resolved_selections =
647 resolve_multiple(adjusted_disjoint.iter(), &self.buffer()).collect();
648 self.select::<usize>(resolved_selections);
649 }
650
651 if let Some(pending) = pending.as_mut() {
652 let buffer = self.buffer();
653 let anchors =
654 buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
655 let (_, start, kept_start) = anchors[0].clone();
656 let (_, end, kept_end) = anchors[1].clone();
657 let kept_head = if pending.selection.reversed {
658 kept_start
659 } else {
660 kept_end
661 };
662 if !kept_head {
663 selections_with_lost_position.insert(
664 pending.selection.id,
665 pending.selection.head().excerpt_id.clone(),
666 );
667 }
668
669 pending.selection.start = start;
670 pending.selection.end = end;
671 }
672 self.collection.pending = pending;
673
674 selections_with_lost_position
675 }
676}
677
678impl<'a> Deref for MutableSelectionsCollection<'a> {
679 type Target = SelectionsCollection;
680 fn deref(&self) -> &Self::Target {
681 self.collection
682 }
683}
684
685// Panics if passed selections are not in order
686pub fn resolve_multiple<'a, D, I>(
687 selections: I,
688 snapshot: &MultiBufferSnapshot,
689) -> impl 'a + Iterator<Item = Selection<D>>
690where
691 D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
692 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
693{
694 let (to_summarize, selections) = selections.into_iter().tee();
695 let mut summaries = snapshot
696 .summaries_for_anchors::<D, _>(
697 to_summarize
698 .flat_map(|s| [&s.start, &s.end])
699 .collect::<Vec<_>>(),
700 )
701 .into_iter();
702 selections.map(move |s| Selection {
703 id: s.id,
704 start: summaries.next().unwrap(),
705 end: summaries.next().unwrap(),
706 reversed: s.reversed,
707 goal: s.goal,
708 })
709}
710
711fn resolve<D: TextDimension + Ord + Sub<D, Output = D>>(
712 selection: &Selection<Anchor>,
713 buffer: &MultiBufferSnapshot,
714) -> Selection<D> {
715 selection.map(|p| p.summary::<D>(&buffer))
716}
717
718fn reset_biases(
719 mut selection: Selection<Anchor>,
720 buffer: &MultiBufferSnapshot,
721) -> Selection<Anchor> {
722 let end_bias = if selection.end.to_offset(buffer) > selection.start.to_offset(buffer) {
723 Bias::Left
724 } else {
725 Bias::Right
726 };
727 selection.start = buffer.anchor_after(selection.start);
728 selection.end = buffer.anchor_at(selection.end, end_bias);
729 selection
730}