Skip to content

Commit

Permalink
Added command
Browse files Browse the repository at this point in the history
Rewrote command, added test

Moved keymap

Refactoring command, added test coverage

Added primary index calculation

Moving primary_index calculation

Refactored code to use fold instead of loop

Changed to use dedup_by

Removed duplicate merge call

Fix primary index calculation
  • Loading branch information
DylanBulfin committed Dec 13, 2022
1 parent 0f2ae35 commit a0b7fd7
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
71 changes: 71 additions & 0 deletions helix-core/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,31 @@ impl Selection {
self
}

// Merges all ranges that are consecutive
pub fn merge_consecutive_ranges(mut self) -> Self {
let mut primary = self.ranges[self.primary_index];

self.ranges.dedup_by(|curr_range, prev_range| {
if prev_range.to() == curr_range.from() {
if prev_range == &primary || curr_range == &primary {
primary = curr_range.merge(*prev_range);
}
*prev_range = curr_range.merge(*prev_range);
true
} else {
false
}
});

self.primary_index = self
.ranges
.iter()
.position(|&range| range == primary)
.unwrap();

self
}

// TODO: consume an iterator or a vec to reduce allocations?
#[must_use]
pub fn new(ranges: SmallVec<[Range; 1]>, primary_index: usize) -> Self {
Expand Down Expand Up @@ -1132,6 +1157,52 @@ mod test {
&["", "abcd", "efg", "rs", "xyz"]
);
}

#[test]
fn test_merge_consecutive_ranges() {
let selection = Selection::new(
smallvec![
Range::new(0, 1),
Range::new(1, 10),
Range::new(15, 20),
Range::new(25, 26),
Range::new(26, 30)
],
4,
);

let result = selection.merge_consecutive_ranges();

assert_eq!(
result.ranges(),
&[Range::new(0, 10), Range::new(15, 20), Range::new(25, 30)]
);
assert_eq!(result.primary_index, 2);

let selection = Selection::new(smallvec![Range::new(0, 1)], 0);
let result = selection.merge_consecutive_ranges();

assert_eq!(result.ranges(), &[Range::new(0, 1)]);
assert_eq!(result.primary_index, 0);

let selection = Selection::new(
smallvec![
Range::new(0, 1),
Range::new(1, 5),
Range::new(5, 8),
Range::new(8, 10),
Range::new(10, 15),
Range::new(18, 25)
],
3,
);

let result = selection.merge_consecutive_ranges();

assert_eq!(result.ranges(), &[Range::new(0, 15), Range::new(18, 25)]);
assert_eq!(result.primary_index, 0);
}

#[test]
fn test_selection_contains() {
fn contains(a: Vec<(usize, usize)>, b: Vec<(usize, usize)>) -> bool {
Expand Down
7 changes: 7 additions & 0 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ impl MappableCommand {
select_regex, "Select all regex matches inside selections",
split_selection, "Split selections on regex matches",
split_selection_on_newline, "Split selection on newlines",
merge_consecutive_ranges, "Merge consecutive ranges",
search, "Search for regex pattern",
rsearch, "Reverse search for regex pattern",
search_next, "Select next search match",
Expand Down Expand Up @@ -1589,6 +1590,12 @@ fn split_selection_on_newline(cx: &mut Context) {
doc.set_selection(view.id, selection);
}

fn merge_consecutive_ranges(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let selection = doc.selection(view.id).clone().merge_consecutive_ranges();
doc.set_selection(view.id, selection);
}

#[allow(clippy::too_many_arguments)]
fn search_impl(
editor: &mut Editor,
Expand Down
1 change: 1 addition & 0 deletions helix-term/src/keymap/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub fn default() -> HashMap<Mode, Keymap> {

"s" => select_regex,
"A-s" => split_selection_on_newline,
"A-_" => merge_consecutive_ranges,
"S" => split_selection,
";" => collapse_selection,
"A-;" => flip_selections,
Expand Down

0 comments on commit a0b7fd7

Please sign in to comment.