1use std::cmp::{max, min, Ordering};
2
3use lapce_xi_rope::{RopeDelta, Transformer};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use crate::cursor::ColPosition;
8
9#[derive(Copy, Clone)]
12pub enum InsertDrift {
13 Inside,
15 Outside,
17 Default,
19}
20
21#[derive(Clone, Copy, PartialEq, Debug)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct SelRegion {
24 pub start: usize,
26 pub end: usize,
28 pub horiz: Option<ColPosition>,
30}
31
32#[derive(Clone, PartialEq, Debug)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct Selection {
37 regions: Vec<SelRegion>,
38 last_inserted: usize,
39}
40
41impl AsRef<Selection> for Selection {
42 fn as_ref(&self) -> &Selection {
43 self
44 }
45}
46
47impl SelRegion {
48 pub fn new(start: usize, end: usize, horiz: Option<ColPosition>) -> SelRegion {
50 SelRegion { start, end, horiz }
51 }
52
53 pub fn caret(offset: usize) -> SelRegion {
56 SelRegion {
57 start: offset,
58 end: offset,
59 horiz: None,
60 }
61 }
62
63 pub fn min(self) -> usize {
75 min(self.start, self.end)
76 }
77
78 pub fn max(self) -> usize {
90 max(self.start, self.end)
91 }
92
93 pub fn is_caret(self) -> bool {
103 self.start == self.end
104 }
105
106 pub fn merge_with(self, other: SelRegion) -> SelRegion {
117 let is_forward = self.end >= self.start;
118 let new_min = min(self.min(), other.min());
119 let new_max = max(self.max(), other.max());
120 let (start, end) = if is_forward {
121 (new_min, new_max)
122 } else {
123 (new_max, new_min)
124 };
125 SelRegion::new(start, end, None)
126 }
127
128 fn should_merge(self, other: SelRegion) -> bool {
129 other.min() < self.max()
130 || ((self.is_caret() || other.is_caret()) && other.min() == self.max())
131 }
132
133 fn contains(&self, offset: usize) -> bool {
134 self.min() <= offset && offset <= self.max()
135 }
136}
137
138impl Selection {
139 pub fn new() -> Selection {
141 Selection {
142 regions: Vec::new(),
143 last_inserted: 0,
144 }
145 }
146
147 pub fn caret(offset: usize) -> Selection {
149 Selection {
150 regions: vec![SelRegion::caret(offset)],
151 last_inserted: 0,
152 }
153 }
154
155 pub fn region(start: usize, end: usize) -> Self {
158 Self::sel_region(SelRegion {
159 start,
160 end,
161 horiz: None,
162 })
163 }
164
165 pub fn sel_region(region: SelRegion) -> Self {
167 Self {
168 regions: vec![region],
169 last_inserted: 0,
170 }
171 }
172
173 pub fn contains(&self, offset: usize) -> bool {
186 for region in self.regions.iter() {
187 if region.contains(offset) {
188 return true;
189 }
190 }
191 false
192 }
193
194 pub fn regions(&self) -> &[SelRegion] {
196 &self.regions
197 }
198
199 pub fn regions_mut(&mut self) -> &mut [SelRegion] {
201 &mut self.regions
202 }
203
204 pub fn min(&self) -> Selection {
222 let mut selection = Self::new();
223 for region in &self.regions {
224 let new_region = SelRegion::new(region.min(), region.min(), None);
225 selection.add_region(new_region);
226 }
227 selection
228 }
229
230 pub fn first(&self) -> Option<&SelRegion> {
232 self.regions.first()
233 }
234
235 pub fn last(&self) -> Option<&SelRegion> {
237 self.regions.get(self.len() - 1)
238 }
239
240 pub fn last_inserted(&self) -> Option<&SelRegion> {
242 self.regions.get(self.last_inserted)
243 }
244
245 pub fn last_inserted_mut(&mut self) -> Option<&mut SelRegion> {
247 self.regions.get_mut(self.last_inserted)
248 }
249
250 pub fn len(&self) -> usize {
252 self.regions.len()
253 }
254
255 pub fn is_caret(&self) -> bool {
258 self.regions.iter().all(|region| region.is_caret())
259 }
260
261 pub fn is_empty(&self) -> bool {
263 self.len() == 0
264 }
265
266 pub fn min_offset(&self) -> usize {
281 let mut offset = self.regions()[0].min();
282 for region in &self.regions {
283 offset = offset.min(region.min());
284 }
285 offset
286 }
287
288 pub fn max_offset(&self) -> usize {
303 let mut offset = self.regions()[0].max();
304 for region in &self.regions {
305 offset = offset.max(region.max());
306 }
307 offset
308 }
309
310 pub fn regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
330 let first = self.search(start);
331 let mut last = self.search(end);
332 if last < self.regions.len() && self.regions[last].min() <= end {
333 last += 1;
334 }
335 &self.regions[first..last]
336 }
337
338 pub fn full_regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
356 let first = self.search_min(start);
357 let mut last = self.search_min(end);
358 if last < self.regions.len() && self.regions[last].min() <= end {
359 last += 1;
360 }
361 &self.regions[first..last]
362 }
363
364 pub fn delete_range(&mut self, start: usize, end: usize) {
379 let mut first = self.search(start);
380 let mut last = self.search(end);
381 if first >= self.regions.len() {
382 return;
383 }
384 if self.regions[first].max() == start {
385 first += 1;
386 }
387 if last < self.regions.len() && self.regions[last].min() < end {
388 last += 1;
389 }
390 remove_n_at(&mut self.regions, first, last - first);
391 }
392
393 pub fn add_region(&mut self, region: SelRegion) {
415 let mut ix = self.search(region.min());
416 if ix == self.regions.len() {
417 self.regions.push(region);
418 self.last_inserted = self.regions.len() - 1;
419 return;
420 }
421 let mut region = region;
422 let mut end_ix = ix;
423 if self.regions[ix].min() <= region.min() {
424 if self.regions[ix].should_merge(region) {
425 region = self.regions[ix].merge_with(region);
426 } else {
427 ix += 1;
428 }
429 end_ix += 1;
430 }
431 while end_ix < self.regions.len() && region.should_merge(self.regions[end_ix]) {
432 region = self.regions[end_ix].merge_with(region);
433 end_ix += 1;
434 }
435 if ix == end_ix {
436 self.regions.insert(ix, region);
437 self.last_inserted = ix;
438 } else {
439 self.regions[ix] = region;
440 remove_n_at(&mut self.regions, ix + 1, end_ix - ix - 1);
441 }
442 }
443
444 pub fn add_range_distinct(&mut self, region: SelRegion) -> (usize, usize) {
452 let mut ix = self.search(region.min());
453
454 if ix < self.regions.len() && self.regions[ix].max() == region.min() {
455 ix += 1;
456 }
457
458 if ix < self.regions.len() {
459 let occ = &self.regions[ix];
461 let is_eq = occ.min() == region.min() && occ.max() == region.max();
462 let is_intersect_before = region.min() >= occ.min() && occ.max() > region.min();
463 if is_eq || is_intersect_before {
464 return (occ.min(), occ.max());
465 }
466 }
467
468 let mut last = self.search(region.max());
470 if last < self.regions.len() && self.regions[last].min() < region.max() {
471 last += 1;
472 }
473 remove_n_at(&mut self.regions, ix, last - ix);
474
475 if ix == self.regions.len() {
476 self.regions.push(region);
477 } else {
478 self.regions.insert(ix, region);
479 }
480
481 (self.regions[ix].min(), self.regions[ix].max())
482 }
483
484 pub fn apply_delta(&self, delta: &RopeDelta, after: bool, drift: InsertDrift) -> Selection {
491 let mut result = Selection::new();
492 let mut transformer = Transformer::new(delta);
493 for region in self.regions() {
494 let is_region_forward = region.start < region.end;
495
496 let (start_after, end_after) = match (drift, region.is_caret()) {
497 (InsertDrift::Inside, false) => (!is_region_forward, is_region_forward),
498 (InsertDrift::Outside, false) => (is_region_forward, !is_region_forward),
499 _ => (after, after),
500 };
501
502 let new_region = SelRegion::new(
503 transformer.transform(region.start, start_after),
504 transformer.transform(region.end, end_after),
505 None,
506 );
507 result.add_region(new_region);
508 }
509 result
510 }
511
512 pub fn get_cursor_offset(&self) -> usize {
514 if self.is_empty() {
515 return 0;
516 }
517 self.regions[self.last_inserted].end
518 }
519
520 pub fn replace_last_inserted_region(&mut self, region: SelRegion) {
522 if self.is_empty() {
523 self.add_region(region);
524 return;
525 }
526
527 self.regions.remove(self.last_inserted);
528 self.add_region(region);
529 }
530
531 fn search(&self, offset: usize) -> usize {
532 if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
533 return self.regions.len();
534 }
535 match self.regions.binary_search_by(|r| r.max().cmp(&offset)) {
536 Ok(ix) => ix,
537 Err(ix) => ix,
538 }
539 }
540
541 fn search_min(&self, offset: usize) -> usize {
542 if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
543 return self.regions.len();
544 }
545 match self
546 .regions
547 .binary_search_by(|r| r.min().cmp(&(offset + 1)))
548 {
549 Ok(ix) => ix,
550 Err(ix) => ix,
551 }
552 }
553}
554
555impl Default for Selection {
556 fn default() -> Self {
557 Self::new()
558 }
559}
560
561fn remove_n_at<T>(v: &mut Vec<T>, index: usize, n: usize) {
562 match n.cmp(&1) {
563 Ordering::Equal => {
564 v.remove(index);
565 }
566 Ordering::Greater => {
567 v.drain(index..index + n);
568 }
569 _ => (),
570 };
571}
572
573#[cfg(test)]
574mod test {
575 use crate::{
576 buffer::Buffer,
577 editor::EditType,
578 selection::{InsertDrift, SelRegion, Selection},
579 };
580
581 #[test]
582 fn should_return_selection_region_min() {
583 let region = SelRegion::new(1, 10, None);
584 assert_eq!(region.min(), region.start);
585
586 let region = SelRegion::new(42, 1, None);
587 assert_eq!(region.min(), region.end);
588 }
589
590 #[test]
591 fn should_return_selection_region_max() {
592 let region = SelRegion::new(1, 10, None);
593 assert_eq!(region.max(), region.end);
594
595 let region = SelRegion::new(42, 1, None);
596 assert_eq!(region.max(), region.start);
597 }
598
599 #[test]
600 fn is_caret_should_return_true() {
601 let region = SelRegion::new(1, 10, None);
602 assert!(!region.is_caret());
603 }
604
605 #[test]
606 fn is_caret_should_return_false() {
607 let region = SelRegion::new(1, 1, None);
608 assert!(region.is_caret());
609 }
610
611 #[test]
612 fn should_merge_regions() {
613 let region = SelRegion::new(1, 2, None);
614 let other = SelRegion::new(3, 4, None);
615 assert_eq!(region.merge_with(other), SelRegion::new(1, 4, None));
616
617 let region = SelRegion::new(2, 1, None);
618 let other = SelRegion::new(4, 3, None);
619 assert_eq!(region.merge_with(other), SelRegion::new(4, 1, None));
620
621 let region = SelRegion::new(1, 1, None);
622 let other = SelRegion::new(6, 6, None);
623 assert_eq!(region.merge_with(other), SelRegion::new(1, 6, None));
624 }
625
626 #[test]
627 fn selection_should_be_caret() {
628 let mut selection = Selection::new();
629 selection.add_region(SelRegion::caret(1));
630 selection.add_region(SelRegion::caret(6));
631 assert!(selection.is_caret());
632 }
633
634 #[test]
635 fn selection_should_not_be_caret() {
636 let mut selection = Selection::new();
637 selection.add_region(SelRegion::caret(1));
638 selection.add_region(SelRegion::new(4, 6, None));
639 assert!(!selection.is_caret());
640 }
641
642 #[test]
643 fn should_return_min_selection() {
644 let mut selection = Selection::new();
645 selection.add_region(SelRegion::new(1, 3, None));
646 selection.add_region(SelRegion::new(4, 6, None));
647 assert_eq!(
648 selection.min().regions,
649 vec![SelRegion::caret(1), SelRegion::caret(4)]
650 );
651 }
652
653 #[test]
654 fn selection_should_contains_region() {
655 let selection = Selection::region(0, 2);
656 assert!(selection.contains(0));
657 assert!(selection.contains(1));
658 assert!(selection.contains(2));
659 assert!(!selection.contains(3));
660 }
661
662 #[test]
663 fn should_return_last_inserted_region() {
664 let mut selection = Selection::region(5, 6);
665 selection.add_region(SelRegion::caret(1));
666 assert_eq!(selection.last_inserted(), Some(&SelRegion::caret(1)));
667 }
668
669 #[test]
670 fn should_return_last_region() {
671 let mut selection = Selection::region(5, 6);
672 selection.add_region(SelRegion::caret(1));
673 assert_eq!(selection.last(), Some(&SelRegion::new(5, 6, None)));
674 }
675
676 #[test]
677 fn should_return_first_region() {
678 let mut selection = Selection::region(5, 6);
679 selection.add_region(SelRegion::caret(1));
680 assert_eq!(selection.first(), Some(&SelRegion::caret(1)));
681 }
682
683 #[test]
684 fn should_return_regions_in_range() {
685 let mut selection = Selection::new();
686 selection.add_region(SelRegion::new(0, 3, None));
687 selection.add_region(SelRegion::new(3, 6, None));
688 selection.add_region(SelRegion::new(7, 8, None));
689 selection.add_region(SelRegion::new(9, 11, None));
690
691 let regions = selection.regions_in_range(5, 10);
692
693 assert_eq!(
694 regions,
695 vec![
696 SelRegion::new(3, 6, None),
697 SelRegion::new(7, 8, None),
698 SelRegion::new(9, 11, None),
699 ]
700 );
701 }
702
703 #[test]
704 fn should_return_regions_in_full_range() {
705 let mut selection = Selection::new();
706 selection.add_region(SelRegion::new(0, 3, None));
707 selection.add_region(SelRegion::new(3, 6, None));
708 selection.add_region(SelRegion::new(7, 8, None));
709 selection.add_region(SelRegion::new(9, 11, None));
710
711 let regions = selection.full_regions_in_range(5, 10);
712
713 assert_eq!(
714 regions,
715 vec![SelRegion::new(7, 8, None), SelRegion::new(9, 11, None),]
716 );
717 }
718
719 #[test]
720 fn should_delete_regions() {
721 let mut selection = Selection::new();
722 selection.add_region(SelRegion::new(0, 3, None));
723 selection.add_region(SelRegion::new(3, 6, None));
724 selection.add_region(SelRegion::new(7, 8, None));
725 selection.add_region(SelRegion::new(9, 11, None));
726 selection.delete_range(5, 10);
727 assert_eq!(selection.regions(), vec![SelRegion::new(0, 3, None)]);
728 }
729
730 #[test]
731 fn should_add_regions() {
732 let mut selection = Selection::new();
733 selection.add_region(SelRegion::new(0, 3, None));
734 selection.add_region(SelRegion::new(3, 6, None));
735 assert_eq!(
736 selection.regions(),
737 vec![SelRegion::new(0, 3, None), SelRegion::new(3, 6, None),]
738 );
739 }
740
741 #[test]
742 fn should_add_and_merge_regions() {
743 let mut selection = Selection::new();
744
745 selection.add_region(SelRegion::new(0, 4, None));
746 selection.add_region(SelRegion::new(3, 6, None));
747 assert_eq!(selection.regions(), vec![SelRegion::new(0, 6, None)]);
748 }
749
750 #[test]
751 fn should_apply_delta_after_insertion() {
752 let selection = Selection::caret(0);
753
754 let (_, mock_delta, _) = {
755 let mut buffer = Buffer::new("");
756 buffer.edit(&[(selection.clone(), "Hello")], EditType::InsertChars)
757 };
758
759 assert_eq!(
760 selection.apply_delta(&mock_delta, true, InsertDrift::Inside),
761 Selection::caret(5)
762 );
763 }
764}