Simplify some more code.

This commit is contained in:
Blaž Hrastnik 2020-09-13 23:38:54 +09:00
parent 0427acd18c
commit 96db02742e
4 changed files with 16 additions and 23 deletions

View file

@ -62,8 +62,8 @@ pub fn append_mode(state: &mut State, _count: usize) {
// TODO: I, A, o and O can share a lot of the primitives. // TODO: I, A, o and O can share a lot of the primitives.
// calculate line numbers for each selection range
fn selection_lines(state: &State) -> Vec<usize> { fn selection_lines(state: &State) -> Vec<usize> {
// calculate line numbers for each selection range
let mut lines = state let mut lines = state
.selection .selection
.ranges() .ranges()

View file

@ -100,8 +100,8 @@ impl Range {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Selection { pub struct Selection {
// TODO: decide how many ranges to inline SmallVec<[Range; 1]> // TODO: decide how many ranges to inline SmallVec<[Range; 1]>
pub(crate) ranges: SmallVec<[Range; 1]>, ranges: SmallVec<[Range; 1]>,
pub(crate) primary_index: usize, primary_index: usize,
} }
impl Selection { impl Selection {
@ -205,6 +205,14 @@ impl Selection {
} }
} }
// fast path for a single selection (cursor)
if ranges.len() == 1 {
return Selection {
ranges,
primary_index: 0,
};
}
// TODO: only normalize if needed (any ranges out of order) // TODO: only normalize if needed (any ranges out of order)
normalize(ranges, primary_index) normalize(ranges, primary_index)
} }

View file

@ -122,7 +122,7 @@ impl State {
// TODO: move all selections according to normal cursor move semantics by collapsing it // TODO: move all selections according to normal cursor move semantics by collapsing it
// into cursors and moving them vertically // into cursors and moving them vertically
let ranges = self.selection.ranges.iter().map(|range| { self.selection.transform(|range| {
// let pos = if !range.is_empty() { // let pos = if !range.is_empty() {
// // if selection already exists, bump it to the start or end of current select first // // if selection already exists, bump it to the start or end of current select first
// if dir == Direction::Backward { // if dir == Direction::Backward {
@ -134,10 +134,7 @@ impl State {
let pos = self.move_pos(range.head, dir, granularity, count); let pos = self.move_pos(range.head, dir, granularity, count);
// }; // };
SelectionRange::new(pos, pos) SelectionRange::new(pos, pos)
}); })
Selection::new(ranges.collect(), self.selection.primary_index)
// TODO: update selection in state via transaction
} }
pub fn extend_selection( pub fn extend_selection(
@ -146,13 +143,10 @@ impl State {
granularity: Granularity, granularity: Granularity,
count: usize, count: usize,
) -> Selection { ) -> Selection {
let ranges = self.selection.ranges.iter().map(|range| { self.selection.transform(|range| {
let pos = self.move_pos(range.head, dir, granularity, count); let pos = self.move_pos(range.head, dir, granularity, count);
SelectionRange::new(range.anchor, pos) SelectionRange::new(range.anchor, pos)
}); })
Selection::new(ranges.collect(), self.selection.primary_index)
// TODO: update selection in state via transaction
} }
} }
@ -203,7 +197,6 @@ mod test {
fn test_coords_at_pos() { fn test_coords_at_pos() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ"); let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0)); assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0));
// TODO: what is the coordinate of newline?
assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5)); // position on \n assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5)); // position on \n
assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0)); // position on w assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0)); // position on w
assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1)); // position on o assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1)); // position on o

View file

@ -3,13 +3,6 @@ use crate::{Rope, Selection, SelectionRange, State, Tendril};
/// (from, to, replacement) /// (from, to, replacement)
pub type Change = (usize, usize, Option<Tendril>); pub type Change = (usize, usize, Option<Tendril>);
// TODO: divided into three different operations, I sort of like having just
// Splice { extent, Option<text>, distance } better.
// insert: Splice { extent: 0, text: Some("a"), distance: 2 }
// delete: Splice { extent: 2, text: None, distance: 2 }
// replace: Splice { extent: 2, text: Some("abc"), distance: 2 }
// unchanged?: Splice { extent: 0, text: None, distance: 2 }
// harder to compose though.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
enum Operation { enum Operation {
/// Move cursor by n characters. /// Move cursor by n characters.
@ -364,7 +357,6 @@ impl Transaction {
let mut last = 0; let mut last = 0;
for (from, to, tendril) in changes { for (from, to, tendril) in changes {
// TODO: need to fill the in-between ranges too
// Retain from last "to" to current "from" // Retain from last "to" to current "from"
acc.push(Operation::Retain(from - last)); acc.push(Operation::Retain(from - last));
match tendril { match tendril {
@ -383,7 +375,7 @@ impl Transaction {
where where
F: Fn(&SelectionRange) -> Change, F: Fn(&SelectionRange) -> Change,
{ {
Self::change(state, state.selection.ranges.iter().map(f)) Self::change(state, state.selection.ranges().iter().map(f))
} }
/// Insert text at each selection head. /// Insert text at each selection head.