redox_core/buffer/text_buffer/
editing.rs1use ropey::Rope;
13
14use crate::buffer::{Edit, Pos, Selection, TextBuffer};
15
16impl TextBuffer {
17 pub fn insert(&mut self, pos: Pos, text: &str) -> Pos {
24 let at = self.pos_to_char(pos);
25 self.rope.insert(at, text);
26
27 let inserted_chars = Rope::from_str(text).len_chars();
30 self.char_to_pos(at + inserted_chars)
31 }
32
33 pub fn delete_range(&mut self, a: Pos, b: Pos) -> Pos {
37 let start = self.pos_to_char(crate::buffer::util::min_pos(self, a, b));
38 let end = self.pos_to_char(crate::buffer::util::max_pos(self, a, b));
39
40 if start < end {
41 self.rope.remove(start..end);
42 }
43
44 self.char_to_pos(start)
45 }
46
47 pub fn delete_selection(&mut self, sel: Selection) -> (Pos, bool) {
49 if sel.is_empty() {
50 return (self.clamp_pos(sel.cursor), false);
51 }
52
53 let (start, end) = sel.ordered();
54 let new_cursor = self.delete_range(start, end);
55 (new_cursor, true)
56 }
57
58 pub fn backspace(&mut self, sel: Selection) -> Selection {
64 if !sel.is_empty() {
65 let (cursor, _) = self.delete_selection(sel);
66 return Selection::empty(cursor);
67 }
68
69 let cursor = self.clamp_pos(sel.cursor);
70 let at = self.pos_to_char(cursor);
71 if at == 0 {
72 return Selection::empty(cursor);
73 }
74
75 let start = at - 1;
76 self.rope.remove(start..at);
77 let new_cursor = self.char_to_pos(start);
78 Selection::empty(new_cursor)
79 }
80
81 pub fn delete(&mut self, sel: Selection) -> Selection {
87 if !sel.is_empty() {
88 let (cursor, _) = self.delete_selection(sel);
89 return Selection::empty(cursor);
90 }
91
92 let cursor = self.clamp_pos(sel.cursor);
93 let at = self.pos_to_char(cursor);
94 let maxc = self.len_chars();
95
96 if at >= maxc {
97 return Selection::empty(cursor);
98 }
99
100 self.rope.remove(at..at + 1);
101 let new_cursor = self.char_to_pos(at);
102 Selection::empty(new_cursor)
103 }
104
105 pub fn insert_newline(&mut self, sel: Selection) -> Selection {
109 if !sel.is_empty() {
110 let (start, end) = sel.ordered();
111 let cursor = self.delete_range(start, end);
112 let new_cursor = self.insert(cursor, "\n");
113 return Selection::empty(new_cursor);
114 }
115
116 let cursor = self.clamp_pos(sel.cursor);
117 let new_cursor = self.insert(cursor, "\n");
118 Selection::empty(new_cursor)
119 }
120
121 pub fn apply_edit(&mut self, edit: Edit) -> Pos {
128 let maxc = self.len_chars();
129 let start = edit.range.start.min(maxc);
130 let end = edit.range.end.min(maxc);
131 let (start, end) = if start <= end {
132 (start, end)
133 } else {
134 (end, start)
135 };
136
137 if start < end {
138 self.rope.remove(start..end);
139 }
140
141 if !edit.insert.is_empty() {
142 self.rope.insert(start, &edit.insert);
143 let inserted_chars = Rope::from_str(&edit.insert).len_chars();
144 self.char_to_pos(start + inserted_chars)
145 } else {
146 self.char_to_pos(start)
147 }
148 }
149
150 pub fn replace_selection(&mut self, sel: Selection, text: &str) -> Selection {
155 if !sel.is_empty() {
156 let (start, end) = sel.ordered();
157 let cursor = self.delete_range(start, end);
158 let cursor = self.insert(cursor, text);
159 Selection::empty(cursor)
160 } else {
161 let cursor = self.insert(sel.cursor, text);
162 Selection::empty(cursor)
163 }
164 }
165}