@@ -19,40 +19,38 @@ use crate::{
19pub type Command = fn(view: &mut View, count: usize);
19pub type Command = fn(view: &mut View, count: usize);
21pub fn move_char_left(view: &mut View, count: usize) {
21pub fn move_char_left(view: &mut View, count: usize) {
22− // TODO: use a transaction
23 let selection =
22 let selection =
26 .move_selection(Direction::Backward, Granularity::Character, count);
25 .move_selection(Direction::Backward, Granularity::Character, count);
27− view.doc.state.selection = selection;
26+ view.doc.set_selection(selection);
30pub fn move_char_right(view: &mut View, count: usize) {
29pub fn move_char_right(view: &mut View, count: usize) {
31− // TODO: use a transaction
32− view.doc.state.selection =
30+ let selection =
35 .move_selection(Direction::Forward, Granularity::Character, count);
33 .move_selection(Direction::Forward, Granularity::Character, count);
34+ view.doc.set_selection(selection);
38pub fn move_line_up(view: &mut View, count: usize) {
37pub fn move_line_up(view: &mut View, count: usize) {
39− // TODO: use a transaction
40− view.doc.state.selection =
38+ let selection = view
43− .move_selection(Direction::Backward, Granularity::Line, count);
41+ .move_selection(Direction::Backward, Granularity::Line, count);
42+ view.doc.set_selection(selection);
46pub fn move_line_down(view: &mut View, count: usize) {
45pub fn move_line_down(view: &mut View, count: usize) {
47− // TODO: use a transaction
48− view.doc.state.selection =
46+ let selection = view
51− .move_selection(Direction::Forward, Granularity::Line, count);
49+ .move_selection(Direction::Forward, Granularity::Line, count);
50+ view.doc.set_selection(selection);
54pub fn move_line_end(view: &mut View, _count: usize) {
53pub fn move_line_end(view: &mut View, _count: usize) {
55− // TODO: use a transaction
56 let lines = selection_lines(&view.doc.state);
54 let lines = selection_lines(&view.doc.state);
58 let positions = lines
56 let positions = lines
@@ -68,9 +66,7 @@ pub fn move_line_end(view: &mut View, _count: usize) {
69 let selection = Selection::new(positions.collect(), 0);
67 let selection = Selection::new(positions.collect(), 0);
71− let transaction = Transaction::new(&mut view.doc.state).with_selection(selection);
69+ view.doc.set_selection(selection);
73− view.doc.apply(&transaction);
76pub fn move_line_start(view: &mut View, _count: usize) {
72pub fn move_line_start(view: &mut View, _count: usize) {
@@ -86,64 +82,58 @@ pub fn move_line_start(view: &mut View, _count: usize) {
87 let selection = Selection::new(positions.collect(), 0);
83 let selection = Selection::new(positions.collect(), 0);
89− let transaction = Transaction::new(&mut view.doc.state).with_selection(selection);
85+ view.doc.set_selection(selection);
91− view.doc.apply(&transaction);
94pub fn move_next_word_start(view: &mut View, count: usize) {
88pub fn move_next_word_start(view: &mut View, count: usize) {
95 let pos = view.doc.state.move_pos(
89 let pos = view.doc.state.move_pos(
96− view.doc.state.selection.cursor(),
90+ view.doc.selection().cursor(),
97 Direction::Forward,
91 Direction::Forward,
98 Granularity::Word,
92 Granularity::Word,
102− // TODO: use a transaction
103− view.doc.state.selection = Selection::single(pos, pos);
96+ view.doc.set_selection(Selection::single(pos, pos));
106pub fn move_prev_word_start(view: &mut View, count: usize) {
99pub fn move_prev_word_start(view: &mut View, count: usize) {
107 let pos = view.doc.state.move_pos(
100 let pos = view.doc.state.move_pos(
108− view.doc.state.selection.cursor(),
101+ view.doc.selection().cursor(),
109 Direction::Backward,
102 Direction::Backward,
110 Granularity::Word,
103 Granularity::Word,
114− // TODO: use a transaction
115− view.doc.state.selection = Selection::single(pos, pos);
107+ view.doc.set_selection(Selection::single(pos, pos));
118pub fn move_next_word_end(view: &mut View, count: usize) {
110pub fn move_next_word_end(view: &mut View, count: usize) {
119 let pos = State::move_next_word_end(
111 let pos = State::move_next_word_end(
120 &view.doc.text().slice(..),
112 &view.doc.text().slice(..),
121− view.doc.state.selection.cursor(),
113+ view.doc.selection().cursor(),
125− // TODO: use a transaction
126− view.doc.state.selection = Selection::single(pos, pos);
117+ view.doc.set_selection(Selection::single(pos, pos));
129pub fn move_file_start(view: &mut View, _count: usize) {
120pub fn move_file_start(view: &mut View, _count: usize) {
130− // TODO: use a transaction
131− view.doc.state.selection = Selection::single(0, 0);
121+ view.doc.set_selection(Selection::single(0, 0));
133 view.doc.mode = Mode::Normal;
123 view.doc.mode = Mode::Normal;
136pub fn move_file_end(view: &mut View, _count: usize) {
126pub fn move_file_end(view: &mut View, _count: usize) {
137− // TODO: use a transaction
138 let text = &view.doc.text();
127 let text = &view.doc.text();
139 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
128 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
140− view.doc.state.selection = Selection::single(last_line, last_line);
130+ .set_selection(Selection::single(last_line, last_line));
142 view.doc.mode = Mode::Normal;
132 view.doc.mode = Mode::Normal;
145pub fn check_cursor_in_view(view: &mut View) -> bool {
135pub fn check_cursor_in_view(view: &mut View) -> bool {
146− let cursor = view.doc.state.selection().cursor();
136+ let cursor = view.doc.selection().cursor();
147 let line = view.doc.text().char_to_line(cursor);
137 let line = view.doc.text().char_to_line(cursor);
148 let document_end = view.first_line + view.size.1.saturating_sub(1) as usize;
138 let document_end = view.first_line + view.size.1.saturating_sub(1) as usize;
@@ -163,7 +153,7 @@ pub fn page_up(view: &mut View, _count: usize) {
163 if !check_cursor_in_view(view) {
153 if !check_cursor_in_view(view) {
164 let text = view.doc.text();
154 let text = view.doc.text();
165 let pos = text.line_to_char(view.last_line().saturating_sub(PADDING));
155 let pos = text.line_to_char(view.last_line().saturating_sub(PADDING));
166− view.doc.state.selection = Selection::single(pos, pos);
156+ view.doc.set_selection(Selection::single(pos, pos));
@@ -173,7 +163,7 @@ pub fn page_down(view: &mut View, _count: usize) {
173 if view.first_line < view.doc.text().len_lines() {
163 if view.first_line < view.doc.text().len_lines() {
174 let text = view.doc.text();
164 let text = view.doc.text();
175 let pos = text.line_to_char(view.first_line as usize);
165 let pos = text.line_to_char(view.first_line as usize);
176− view.doc.state.selection = Selection::single(pos, pos);
166+ view.doc.set_selection(Selection::single(pos, pos));
@@ -187,7 +177,7 @@ pub fn half_page_up(view: &mut View, _count: usize) {
187 if !check_cursor_in_view(view) {
177 if !check_cursor_in_view(view) {
188 let text = &view.doc.text();
178 let text = &view.doc.text();
189 let pos = text.line_to_char(view.last_line() - PADDING);
179 let pos = text.line_to_char(view.last_line() - PADDING);
190− view.doc.state.selection = Selection::single(pos, pos);
180+ view.doc.set_selection(Selection::single(pos, pos));
@@ -199,42 +189,41 @@ pub fn half_page_down(view: &mut View, _count: usize) {
199 if !check_cursor_in_view(view) {
189 if !check_cursor_in_view(view) {
200 let text = view.doc.text();
190 let text = view.doc.text();
201 let pos = text.line_to_char(view.first_line as usize);
191 let pos = text.line_to_char(view.first_line as usize);
202− view.doc.state.selection = Selection::single(pos, pos);
192+ view.doc.set_selection(Selection::single(pos, pos));
205// avoid select by default by having a visual mode switch that makes movements into selects
195// avoid select by default by having a visual mode switch that makes movements into selects
207pub fn extend_char_left(view: &mut View, count: usize) {
197pub fn extend_char_left(view: &mut View, count: usize) {
208− // TODO: use a transaction
209 let selection =
198 let selection =
212 .extend_selection(Direction::Backward, Granularity::Character, count);
201 .extend_selection(Direction::Backward, Granularity::Character, count);
213− view.doc.state.selection = selection;
202+ view.doc.set_selection(selection);
216pub fn extend_char_right(view: &mut View, count: usize) {
205pub fn extend_char_right(view: &mut View, count: usize) {
217− // TODO: use a transaction
218− view.doc.state.selection =
206+ let selection =
221 .extend_selection(Direction::Forward, Granularity::Character, count);
209 .extend_selection(Direction::Forward, Granularity::Character, count);
210+ view.doc.set_selection(selection);
224pub fn extend_line_up(view: &mut View, count: usize) {
213pub fn extend_line_up(view: &mut View, count: usize) {
225− // TODO: use a transaction
226− view.doc.state.selection =
214+ let selection = view
229− .extend_selection(Direction::Backward, Granularity::Line, count);
217+ .extend_selection(Direction::Backward, Granularity::Line, count);
218+ view.doc.set_selection(selection);
232pub fn extend_line_down(view: &mut View, count: usize) {
221pub fn extend_line_down(view: &mut View, count: usize) {
233− // TODO: use a transaction
234− view.doc.state.selection =
222+ let selection = view
237− .extend_selection(Direction::Forward, Granularity::Line, count);
225+ .extend_selection(Direction::Forward, Granularity::Line, count);
226+ view.doc.set_selection(selection);
240pub fn split_selection_on_newline(view: &mut View, _count: usize) {
229pub fn split_selection_on_newline(view: &mut View, _count: usize) {
@@ -242,20 +231,19 @@ pub fn split_selection_on_newline(view: &mut View, _count: usize) {
242 // only compile the regex once
231 // only compile the regex once
243 #[allow(clippy::trivial_regex)]
232 #[allow(clippy::trivial_regex)]
244 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
233 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
245− // TODO: use a transaction
246− view.doc.state.selection = selection::split_on_matches(text, view.doc.state.selection(), ®EX)
234+ let selection = selection::split_on_matches(text, view.doc.selection(), ®EX);
235+ view.doc.set_selection(selection);
249pub fn select_line(view: &mut View, _count: usize) {
238pub fn select_line(view: &mut View, _count: usize) {
250 // TODO: count
239 // TODO: count
251− let pos = view.doc.state.selection().primary();
240+ let pos = view.doc.selection().primary();
252 let text = view.doc.text();
241 let text = view.doc.text();
253 let line = text.char_to_line(pos.head);
242 let line = text.char_to_line(pos.head);
254 let start = text.line_to_char(line);
243 let start = text.line_to_char(line);
255 let end = text.line_to_char(line + 1).saturating_sub(1);
244 let end = text.line_to_char(line + 1).saturating_sub(1);
257− // TODO: use a transaction
258− view.doc.state.selection = Selection::single(start, end);
246+ view.doc.set_selection(Selection::single(start, end));
261pub fn delete_selection(view: &mut View, _count: usize) {
249pub fn delete_selection(view: &mut View, _count: usize) {
@@ -273,19 +261,21 @@ pub fn change_selection(view: &mut View, count: usize) {
275pub fn collapse_selection(view: &mut View, _count: usize) {
263pub fn collapse_selection(view: &mut View, _count: usize) {
276− view.doc.state.selection = view
264+ let selection = view
279− .selection
266+ .selection()
280− .transform(|range| Range::new(range.head, range.head))
267+ .transform(|range| Range::new(range.head, range.head));
269+ view.doc.set_selection(selection);
283pub fn flip_selections(view: &mut View, _count: usize) {
272pub fn flip_selections(view: &mut View, _count: usize) {
284− view.doc.state.selection = view
273+ let selection = view
287− .selection
275+ .selection()
288− .transform(|range| Range::new(range.head, range.anchor))
276+ .transform(|range| Range::new(range.head, range.anchor));
278+ view.doc.set_selection(selection);
291fn enter_insert_mode(view: &mut View) {
281fn enter_insert_mode(view: &mut View) {
@@ -297,11 +287,11 @@ fn enter_insert_mode(view: &mut View) {
297pub fn insert_mode(view: &mut View, _count: usize) {
287pub fn insert_mode(view: &mut View, _count: usize) {
298 enter_insert_mode(view);
288 enter_insert_mode(view);
300− view.doc.state.selection = view
290+ let selection = view
303− .selection
292+ .selection()
304− .transform(|range| Range::new(range.to(), range.from()))
293+ .transform(|range| Range::new(range.to(), range.from()));
294+ view.doc.set_selection(selection);
307// inserts at the end of each selection
297// inserts at the end of each selection
@@ -311,13 +301,14 @@ pub fn append_mode(view: &mut View, _count: usize) {
312 // TODO: as transaction
302 // TODO: as transaction
313 let text = &view.doc.text().slice(..);
303 let text = &view.doc.text().slice(..);
314− view.doc.state.selection = view.doc.state.selection.transform(|range| {
304+ let selection = view.doc.selection().transform(|range| {
315 // TODO: to() + next char
305 // TODO: to() + next char
316 Range::new(
306 Range::new(
317 range.from(),
307 range.from(),
318 graphemes::next_grapheme_boundary(text, range.to()),
308 graphemes::next_grapheme_boundary(text, range.to()),
311+ view.doc.set_selection(selection);
323// TODO: I, A, o and O can share a lot of the primitives.
314// TODO: I, A, o and O can share a lot of the primitives.
@@ -402,7 +393,7 @@ fn append_changes_to_history(view: &mut View) {
402 let changes = std::mem::replace(&mut view.doc.changes, new_changeset);
393 let changes = std::mem::replace(&mut view.doc.changes, new_changeset);
403 // Instead of doing this messy merge we could always commit, and based on transaction
394 // Instead of doing this messy merge we could always commit, and based on transaction
404 // annotations either add a new layer or compose into the previous one.
395 // annotations either add a new layer or compose into the previous one.
405− let transaction = Transaction::from(changes).with_selection(view.doc.state.selection().clone());
396+ let transaction = Transaction::from(changes).with_selection(view.doc.selection().clone());
407 // increment document version
398 // increment document version
408 // TODO: needs to happen on undo/redo too
399 // TODO: needs to happen on undo/redo too
@@ -424,12 +415,13 @@ pub fn normal_mode(view: &mut View, _count: usize) {
424 // if leaving append mode, move cursor back by 1
415 // if leaving append mode, move cursor back by 1
425 if view.doc.restore_cursor {
416 if view.doc.restore_cursor {
426 let text = &view.doc.text().slice(..);
417 let text = &view.doc.text().slice(..);
427− view.doc.state.selection = view.doc.state.selection.transform(|range| {
418+ let selection = view.doc.selection().transform(|range| {
428 Range::new(
419 Range::new(
429 range.from(),
420 range.from(),
430 graphemes::prev_grapheme_boundary(text, range.to()),
421 graphemes::prev_grapheme_boundary(text, range.to()),
424+ view.doc.set_selection(selection);
434 view.doc.restore_cursor = false;
426 view.doc.restore_cursor = false;
@@ -587,7 +579,7 @@ fn get_lines(view: &View) -> Vec<usize> {
587 let mut lines = Vec::new();
579 let mut lines = Vec::new();
589 // Get all line numbers
581 // Get all line numbers
590− for range in view.doc.state.selection.ranges() {
582+ for range in view.doc.selection().ranges() {
591 let start = view.doc.text().char_to_line(range.from());
583 let start = view.doc.text().char_to_line(range.from());
592 let end = view.doc.text().char_to_line(range.to());
584 let end = view.doc.text().char_to_line(range.to());