nimbus_fml/editing/
cursor_position.rs
1use std::ops::Add;
6
7use unicode_segmentation::UnicodeSegmentation;
8
9#[derive(Clone, Debug, Default, PartialEq)]
10pub struct CursorPosition {
11 pub line: u32,
12 pub col: u32,
13}
14
15#[allow(dead_code)]
16impl CursorPosition {
17 pub(crate) fn new(line: usize, col: usize) -> Self {
18 Self {
19 line: line as u32,
20 col: col as u32,
21 }
22 }
23}
24
25impl From<(usize, usize)> for CursorPosition {
26 fn from((line, col): (usize, usize)) -> Self {
27 Self::new(line, col)
28 }
29}
30
31#[derive(Clone, Debug, Default, PartialEq)]
34pub struct CursorSpan {
35 pub from: CursorPosition,
36 pub to: CursorPosition,
37}
38
39impl Add<&str> for CursorPosition {
42 type Output = CursorSpan;
43
44 fn add(self, rhs: &str) -> Self::Output {
45 let mut line_count = 0;
46 let mut last_line = None;
47
48 for line in rhs.lines() {
49 line_count += 1;
50 last_line = Some(line);
51 }
52
53 if rhs.ends_with('\n') {
54 line_count += 1;
55 last_line = None;
56 }
57
58 let last_line_length = match last_line {
59 Some(line) => UnicodeSegmentation::graphemes(line, true).count(),
60 None => 0,
61 } as u32;
62
63 let to = match line_count {
64 0 => self.clone(),
65 1 => CursorPosition {
66 line: self.line,
67 col: self.col + last_line_length,
68 },
69 _ => CursorPosition {
70 line: self.line + line_count - 1,
71 col: last_line_length,
72 },
73 };
74
75 Self::Output { from: self, to }
76 }
77}
78
79impl Add<CursorSpan> for CursorPosition {
80 type Output = CursorSpan;
81
82 fn add(self, rhs: CursorSpan) -> Self::Output {
83 Self::Output {
84 from: self,
85 to: rhs.to,
86 }
87 }
88}
89
90#[cfg(test)]
91mod unit_tests {
92 use super::*;
93
94 #[test]
95 fn test_add_str() {
96 let from = CursorPosition::new(10, 10);
98
99 assert_eq!(CursorPosition::new(10, 10), (from.clone() + "").to);
100 assert_eq!(CursorPosition::new(10, 11), (from.clone() + "0").to);
101 assert_eq!(CursorPosition::new(10, 12), (from.clone() + "01").to);
102
103 assert_eq!(CursorPosition::new(11, 1), (from.clone() + "\n0").to);
104 assert_eq!(CursorPosition::new(12, 1), (from.clone() + "\n\n0").to);
105
106 assert_eq!(CursorPosition::new(11, 0), (from.clone() + "\n").to);
107 assert_eq!(CursorPosition::new(12, 0), (from.clone() + "\n\n").to);
108 }
109}