From 96db02742e85648e4ce0c2ab9b7cd239bdb763f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 13 Sep 2020 23:38:54 +0900 Subject: [PATCH] Simplify some more code. --- helix-core/src/commands.rs | 2 +- helix-core/src/selection.rs | 12 ++++++++++-- helix-core/src/state.rs | 15 ++++----------- helix-core/src/transaction.rs | 10 +--------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/helix-core/src/commands.rs b/helix-core/src/commands.rs index 8dc817da8..6c09c3adf 100644 --- a/helix-core/src/commands.rs +++ b/helix-core/src/commands.rs @@ -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. +// calculate line numbers for each selection range fn selection_lines(state: &State) -> Vec { - // calculate line numbers for each selection range let mut lines = state .selection .ranges() diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index 2ae2d7c8d..80bb6a0c1 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -100,8 +100,8 @@ pub fn extend(&self, from: usize, to: usize) -> Self { #[derive(Debug, Clone)] pub struct Selection { // TODO: decide how many ranges to inline SmallVec<[Range; 1]> - pub(crate) ranges: SmallVec<[Range; 1]>, - pub(crate) primary_index: usize, + ranges: SmallVec<[Range; 1]>, + primary_index: usize, } impl Selection { @@ -205,6 +205,14 @@ pub fn single(anchor: usize, head: usize) -> Self { } } + // 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) normalize(ranges, primary_index) } diff --git a/helix-core/src/state.rs b/helix-core/src/state.rs index 511df8fec..be2b33172 100644 --- a/helix-core/src/state.rs +++ b/helix-core/src/state.rs @@ -122,7 +122,7 @@ pub fn move_selection( // TODO: move all selections according to normal cursor move semantics by collapsing it // into cursors and moving them vertically - let ranges = self.selection.ranges.iter().map(|range| { + self.selection.transform(|range| { // let pos = if !range.is_empty() { // // if selection already exists, bump it to the start or end of current select first // if dir == Direction::Backward { @@ -134,10 +134,7 @@ pub fn move_selection( let pos = self.move_pos(range.head, dir, granularity, count); // }; SelectionRange::new(pos, pos) - }); - - Selection::new(ranges.collect(), self.selection.primary_index) - // TODO: update selection in state via transaction + }) } pub fn extend_selection( @@ -146,13 +143,10 @@ pub fn extend_selection( granularity: Granularity, count: usize, ) -> Selection { - let ranges = self.selection.ranges.iter().map(|range| { + self.selection.transform(|range| { let pos = self.move_pos(range.head, dir, granularity, count); 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() { let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ"); 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(..), 6), (1, 0)); // position on w assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1)); // position on o diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index 4ecc575a8..b4cc83c6a 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -3,13 +3,6 @@ /// (from, to, replacement) pub type Change = (usize, usize, Option); -// TODO: divided into three different operations, I sort of like having just -// Splice { extent, Option, 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)] enum Operation { /// Move cursor by n characters. @@ -364,7 +357,6 @@ pub fn change(state: &State, changes: I) -> Self let mut last = 0; for (from, to, tendril) in changes { - // TODO: need to fill the in-between ranges too // Retain from last "to" to current "from" acc.push(Operation::Retain(from - last)); match tendril { @@ -383,7 +375,7 @@ pub fn change_by_selection(state: &State, f: F) -> Self where 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.