redox_core/buffer/text_buffer/
words.rs1use super::super::util::is_word_char;
11use super::TextBuffer;
12use crate::buffer::Pos;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15enum CharClass {
16 Whitespace,
17 Keyword,
18 Symbol,
19}
20
21#[inline]
22fn classify(ch: char) -> CharClass {
23 if ch.is_whitespace() {
24 CharClass::Whitespace
25 } else if is_word_char(ch) {
26 CharClass::Keyword
27 } else {
28 CharClass::Symbol
29 }
30}
31
32impl TextBuffer {
33 pub fn word_start_before(&self, pos: Pos) -> Pos {
35 let mut c = self.pos_to_char(pos);
36 if c == 0 {
37 return Pos::zero();
38 }
39
40 while c > 0 && classify(self.rope.char(c - 1)) == CharClass::Whitespace {
41 c -= 1;
42 }
43
44 if c == 0 {
45 return Pos::zero();
46 }
47
48 let target = classify(self.rope.char(c - 1));
49 while c > 0 && classify(self.rope.char(c - 1)) == target {
50 c -= 1;
51 }
52
53 self.char_to_pos(c)
54 }
55
56 pub fn word_end_after(&self, pos: Pos) -> Pos {
58 let mut c = self.pos_to_char(pos);
59 let maxc = self.len_chars();
60 if c >= maxc {
61 return self.char_to_pos(c);
62 }
63
64 let mut class = classify(self.rope.char(c));
65 if class == CharClass::Whitespace {
66 while c < maxc && classify(self.rope.char(c)) == CharClass::Whitespace {
67 c += 1;
68 }
69 if c >= maxc {
70 return self.char_to_pos(c.saturating_sub(1));
71 }
72 class = classify(self.rope.char(c));
73 } else {
74 let at_end = c + 1 >= maxc || classify(self.rope.char(c + 1)) != class;
75 if at_end {
76 c += 1;
77 while c < maxc && classify(self.rope.char(c)) == CharClass::Whitespace {
78 c += 1;
79 }
80 if c >= maxc {
81 return self.char_to_pos(c.saturating_sub(1));
82 }
83 class = classify(self.rope.char(c));
84 }
85 }
86
87 while c + 1 < maxc && classify(self.rope.char(c + 1)) == class {
88 c += 1;
89 }
90
91 self.char_to_pos(c)
92 }
93
94 pub fn word_start_after(&self, pos: Pos) -> Pos {
96 let mut c = self.pos_to_char(pos);
97 let maxc = self.len_chars();
98 if c >= maxc {
99 return self.char_to_pos(c);
100 }
101
102 let class = classify(self.rope.char(c));
103 if class != CharClass::Whitespace {
104 while c < maxc && classify(self.rope.char(c)) == class {
105 c += 1;
106 }
107 }
108
109 while c < maxc && classify(self.rope.char(c)) == CharClass::Whitespace {
110 c += 1;
111 }
112
113 self.char_to_pos(c)
114 }
115}