on master help sign in
state.rs cleanup
commit9c55b3e306e221c213aadf9caa02a6b180dc7503 authorBlaž Hrastnik <blaz@mxxn.io> dateMon 15 Mar 2021, 14:40 (6 years ago) parentbb87b08
1 file changed+26−61
helix-core/src/state.rs+26−61
helix-core/src/state.rs+26−61
@@ -31,26 +31,6 @@ impl State {
3131 }
3232 }
3333
34− // TODO: doc/selection accessors
35−
36− // TODO: be able to take either Rope or RopeSlice
37− // #[inline]
38− // pub fn doc(&self) -> &Rope {
39− // &self.doc
40− // }
41−
42− // #[inline]
43− // pub fn selection(&self) -> &Selection {
44− // &self.selection
45− // }
46−
47− // pub fn doc<R>(&self, range: R) -> RopeSlice
48− // where
49− // R: std::ops::RangeBounds<usize>,
50− // {
51− // self.doc.slice(range)
52− // }
53−
5434 // update/transact:
5535 // update(desc) => transaction ? transaction.doc() for applied doc
5636 // transaction.apply(doc)
@@ -74,17 +54,6 @@ impl State {
7454 // foldable
7555 // changeFilter/transactionFilter
7656
77− // TODO: move that accepts a boundary matcher fn/list, we keep incrementing until we hit
78− // a boundary
79−
80− // TODO: edits, does each keypress trigger a full command? I guess it's adding to the same
81− // transaction
82− // There should be three pieces of the state: current transaction, the original doc, "preview"
83− // of the new state.
84− // 1. apply the newly generated keypress as a transaction
85− // 2. compose onto a ongoing transaction
86− // 3. on insert mode leave, that transaction gets stored into undo history
87−
8857 pub fn move_range(
8958 &self,
9059 range: Range,
@@ -93,47 +62,42 @@ impl State {
9362 count: usize,
9463 extend: bool,
9564 ) -> Range {
96− let text = &self.doc;
65+ let text = self.doc.slice(..);
9766 let pos = range.head;
98− match (dir, granularity) {
67+ let line = text.char_to_line(pos);
68+ // TODO: we can optimize clamping by passing in RopeSlice limited to current line. that way
69+ // we stop calculating past start/end of line.
70+ let pos = match (dir, granularity) {
9971 (Direction::Backward, Granularity::Character) => {
100− // Clamp to line
101− let line = text.char_to_line(pos);
10272 let start = text.line_to_char(line);
103− let pos = std::cmp::max(
104− nth_prev_grapheme_boundary(text.slice(..), pos, count),
105− start,
106− );
107− Range::new(if extend { range.anchor } else { pos }, pos)
73+ nth_prev_grapheme_boundary(text, pos, count).max(start)
10874 }
10975 (Direction::Forward, Granularity::Character) => {
110− // Clamp to line
111− let line = text.char_to_line(pos);
11276 // Line end is pos at the start of next line - 1
11377 // subtract another 1 because the line ends with \n
11478 let end = text.line_to_char(line + 1).saturating_sub(2);
115− let pos =
116− std::cmp::min(nth_next_grapheme_boundary(text.slice(..), pos, count), end);
117− Range::new(if extend { range.anchor } else { pos }, pos)
79+ nth_next_grapheme_boundary(text, pos, count).min(end)
11880 }
119− (_, Granularity::Line) => move_vertically(text.slice(..), dir, range, count, extend),
120− }
81+ (_, Granularity::Line) => return move_vertically(text, dir, range, count, extend),
82+ };
83+ Range::new(if extend { range.anchor } else { pos }, pos)
12184 }
12285
12386 pub fn move_next_word_start(slice: RopeSlice, mut pos: usize, count: usize) -> usize {
124− // TODO: confirm it's fine without using graphemes, I think it should be
12587 for _ in 0..count {
126− // TODO: if end return end
88+ if pos + 1 == slice.len_chars() {
89+ return pos;
90+ }
12791
128− let ch = slice.char(pos);
129− let next = slice.char(pos.saturating_add(1));
92+ let mut ch = slice.char(pos);
93+ let next = slice.char(pos + 1);
94+
95+ // if we're at the end of a word, or on whitespce right before new one
13096 if categorize(ch) != categorize(next) {
13197 pos += 1;
98+ ch = next;
13299 }
133100
134− // refetch
135− let ch = slice.char(pos);
136−
137101 if is_word(ch) {
138102 skip_over_next(slice, &mut pos, is_word);
139103 } else if ch.is_ascii_punctuation() {
@@ -148,7 +112,6 @@ impl State {
148112 }
149113
150114 pub fn move_prev_word_start(slice: RopeSlice, mut pos: usize, count: usize) -> usize {
151− // TODO: confirm it's fine without using graphemes, I think it should be
152115 for _ in 0..count {
153116 if pos == 0 {
154117 return pos;
@@ -182,11 +145,13 @@ impl State {
182145
183146 pub fn move_next_word_end(slice: RopeSlice, mut pos: usize, count: usize) -> usize {
184147 for _ in 0..count {
185− // TODO: if end return end
148+ if pos + 1 == slice.len_chars() {
149+ return pos;
150+ }
186151
187− // TODO: confirm it's fine without using graphemes, I think it should be
188152 let ch = slice.char(pos);
189− let next = slice.char(pos.saturating_add(1));
153+ let next = slice.char(pos + 1);
154+
190155 if categorize(ch) != categorize(next) {
191156 pos += 1;
192157 }
@@ -202,7 +167,7 @@ impl State {
202167 } else if ch.is_ascii_punctuation() {
203168 skip_over_next(slice, &mut pos, |ch| ch.is_ascii_punctuation());
204169 }
205− pos = pos.saturating_sub(1)
170+ pos -= 1
206171 }
207172
208173 pos
@@ -311,7 +276,7 @@ where
311276 if !fun(ch) {
312277 break;
313278 }
314− *pos += 1; // TODO: can go 1 over end of doc
279+ *pos += 1;
315280 }
316281}
317282
@@ -327,7 +292,7 @@ where
327292 if !fun(ch) {
328293 break;
329294 }
330− *pos -= pos.saturating_sub(1);
295+ *pos = pos.saturating_sub(1);
331296 }
332297}
333298