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