1use crate::{Anchor, Point, TextBuffer, ToOffset as _, ToPoint as _};
2use std::{cmp::Ordering, mem, ops::Range};
3
4pub type SelectionSetId = clock::Lamport;
5pub type SelectionsVersion = usize;
6
7#[derive(Copy, Clone, Debug, Eq, PartialEq)]
8pub enum SelectionGoal {
9 None,
10 Column(u32),
11 ColumnRange { start: u32, end: u32 },
12}
13
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct Selection {
16 pub id: usize,
17 pub start: Anchor,
18 pub end: Anchor,
19 pub reversed: bool,
20 pub goal: SelectionGoal,
21}
22
23impl Selection {
24 pub fn head(&self) -> &Anchor {
25 if self.reversed {
26 &self.start
27 } else {
28 &self.end
29 }
30 }
31
32 pub fn set_head(&mut self, buffer: &TextBuffer, cursor: Anchor) {
33 if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
34 if !self.reversed {
35 mem::swap(&mut self.start, &mut self.end);
36 self.reversed = true;
37 }
38 self.start = cursor;
39 } else {
40 if self.reversed {
41 mem::swap(&mut self.start, &mut self.end);
42 self.reversed = false;
43 }
44 self.end = cursor;
45 }
46 }
47
48 pub fn tail(&self) -> &Anchor {
49 if self.reversed {
50 &self.end
51 } else {
52 &self.start
53 }
54 }
55
56 pub fn point_range(&self, buffer: &TextBuffer) -> Range<Point> {
57 let start = self.start.to_point(buffer);
58 let end = self.end.to_point(buffer);
59 if self.reversed {
60 end..start
61 } else {
62 start..end
63 }
64 }
65
66 pub fn offset_range(&self, buffer: &TextBuffer) -> Range<usize> {
67 let start = self.start.to_offset(buffer);
68 let end = self.end.to_offset(buffer);
69 if self.reversed {
70 end..start
71 } else {
72 start..end
73 }
74 }
75}