on master help sign in
Simplify some more code.
96db027Blaž Hrastnik
helix-core/src/commands.rs+1−1
@@ -62,8 +62,8 @@ pub fn append_mode(state: &mut State, _count: usize) {
62
62
63// TODO: I, A, o and O can share a lot of the primitives.
63// TODO: I, A, o and O can share a lot of the primitives.
64
64
65+// calculate line numbers for each selection range
65fn selection_lines(state: &State) -> Vec<usize> {
66fn selection_lines(state: &State) -> Vec<usize> {
66− // calculate line numbers for each selection range
67 let mut lines = state
67 let mut lines = state
68 .selection
68 .selection
69 .ranges()
69 .ranges()
helix-core/src/selection.rs+10−2
@@ -100,8 +100,8 @@ impl Range {
100#[derive(Debug, Clone)]
100#[derive(Debug, Clone)]
101pub struct Selection {
101pub struct Selection {
102 // TODO: decide how many ranges to inline SmallVec<[Range; 1]>
102 // TODO: decide how many ranges to inline SmallVec<[Range; 1]>
103− pub(crate) ranges: SmallVec<[Range; 1]>,
103+ ranges: SmallVec<[Range; 1]>,
104− pub(crate) primary_index: usize,
104+ primary_index: usize,
105}
105}
106
106
107impl Selection {
107impl Selection {
@@ -205,6 +205,14 @@ impl Selection {
205 }
205 }
206 }
206 }
207
207
208+ // fast path for a single selection (cursor)
209+ if ranges.len() == 1 {
210+ return Selection {
211+ ranges,
212+ primary_index: 0,
213+ };
214+ }
215+
208 // TODO: only normalize if needed (any ranges out of order)
216 // TODO: only normalize if needed (any ranges out of order)
209 normalize(ranges, primary_index)
217 normalize(ranges, primary_index)
210 }
218 }
helix-core/src/state.rs+4−11
@@ -122,7 +122,7 @@ impl State {
122 // TODO: move all selections according to normal cursor move semantics by collapsing it
122 // TODO: move all selections according to normal cursor move semantics by collapsing it
123 // into cursors and moving them vertically
123 // into cursors and moving them vertically
124
124
125− let ranges = self.selection.ranges.iter().map(|range| {
125+ self.selection.transform(|range| {
126 // let pos = if !range.is_empty() {
126 // let pos = if !range.is_empty() {
127 // // if selection already exists, bump it to the start or end of current select first
127 // // if selection already exists, bump it to the start or end of current select first
128 // if dir == Direction::Backward {
128 // if dir == Direction::Backward {
@@ -134,10 +134,7 @@ impl State {
134 let pos = self.move_pos(range.head, dir, granularity, count);
134 let pos = self.move_pos(range.head, dir, granularity, count);
135 // };
135 // };
136 SelectionRange::new(pos, pos)
136 SelectionRange::new(pos, pos)
137− });
137+ })
138−
139− Selection::new(ranges.collect(), self.selection.primary_index)
140− // TODO: update selection in state via transaction
141 }
138 }
142
139
143 pub fn extend_selection(
140 pub fn extend_selection(
@@ -146,13 +143,10 @@ impl State {
146 granularity: Granularity,
143 granularity: Granularity,
147 count: usize,
144 count: usize,
148 ) -> Selection {
145 ) -> Selection {
149− let ranges = self.selection.ranges.iter().map(|range| {
146+ self.selection.transform(|range| {
150 let pos = self.move_pos(range.head, dir, granularity, count);
147 let pos = self.move_pos(range.head, dir, granularity, count);
151 SelectionRange::new(range.anchor, pos)
148 SelectionRange::new(range.anchor, pos)
152− });
149+ })
153−
154− Selection::new(ranges.collect(), self.selection.primary_index)
155− // TODO: update selection in state via transaction
156 }
150 }
157}
151}
158
152
@@ -203,7 +197,6 @@ mod test {
203 fn test_coords_at_pos() {
197 fn test_coords_at_pos() {
204 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
198 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
205 assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0));
199 assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0));
206− // TODO: what is the coordinate of newline?
207 assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5)); // position on \n
200 assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5)); // position on \n
208 assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0)); // position on w
201 assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0)); // position on w
209 assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1)); // position on o
202 assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1)); // position on o
helix-core/src/transaction.rs+1−9
@@ -3,13 +3,6 @@ use crate::{Rope, Selection, SelectionRange, State, Tendril};
3/// (from, to, replacement)
3/// (from, to, replacement)
4pub type Change = (usize, usize, Option<Tendril>);
4pub type Change = (usize, usize, Option<Tendril>);
5
5
6−// TODO: divided into three different operations, I sort of like having just
7−// Splice { extent, Option<text>, distance } better.
8−// insert: Splice { extent: 0, text: Some("a"), distance: 2 }
9−// delete: Splice { extent: 2, text: None, distance: 2 }
10−// replace: Splice { extent: 2, text: Some("abc"), distance: 2 }
11−// unchanged?: Splice { extent: 0, text: None, distance: 2 }
12−// harder to compose though.
13#[derive(Debug, Clone, PartialEq, Eq)]
6#[derive(Debug, Clone, PartialEq, Eq)]
14enum Operation {
7enum Operation {
15 /// Move cursor by n characters.
8 /// Move cursor by n characters.
@@ -364,7 +357,6 @@ impl Transaction {
364
357
365 let mut last = 0;
358 let mut last = 0;
366 for (from, to, tendril) in changes {
359 for (from, to, tendril) in changes {
367− // TODO: need to fill the in-between ranges too
368 // Retain from last "to" to current "from"
360 // Retain from last "to" to current "from"
369 acc.push(Operation::Retain(from - last));
361 acc.push(Operation::Retain(from - last));
370 match tendril {
362 match tendril {
@@ -383,7 +375,7 @@ impl Transaction {
383 where
375 where
384 F: Fn(&SelectionRange) -> Change,
376 F: Fn(&SelectionRange) -> Change,
385 {
377 {
386− Self::change(state, state.selection.ranges.iter().map(f))
378+ Self::change(state, state.selection.ranges().iter().map(f))
387 }
379 }
388
380
389 /// Insert text at each selection head.
381 /// Insert text at each selection head.