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