selection.rs

 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}