From 98c451069d47714da496831cc055e6e9d028eba2 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 30 Aug 2022 21:43:18 -0500 Subject: [PATCH] Add a join_ranges command --- helix-core/src/selection.rs | 13 +++++++++++++ helix-term/src/commands.rs | 16 ++++++++++++++++ helix-term/src/keymap/default.rs | 2 +- helix-term/tests/test/commands.rs | 20 ++++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index 89de87feca570..c79f0f770a5eb 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -678,6 +678,19 @@ impl Selection { Selection::new(ranges, self.primary_index) } + + /// Creates a new selection in which all ranges are merged into one. + /// + /// The new range covers from the lowest [Range::from] to the highest + /// [Range::to]. + pub fn join_ranges(&self) -> Selection { + // SAFETY: selections created with Selection::new are asserted to have + // non-empty range vectors. + let first = self.ranges.first().unwrap(); + let last = self.ranges.last().unwrap(); + + Selection::new(smallvec![first.union(*last)], 0) + } } impl<'a> IntoIterator for &'a Selection { diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index f6aa602656113..970806ee5f266 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -451,6 +451,7 @@ impl MappableCommand { select_shortest_selection_to_register, "Select shortest selection for each pair and save to register", select_longest_selection_from_register, "Select longest selection for each pair from register", select_longest_selection_to_register, "Select longest selection for each pair and save to register", + join_selections, "Join all selections into one", ); } @@ -5117,3 +5118,18 @@ pub mod range_combination { } } } + +fn join_selections(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + let doc_selection = doc.selection(view.id); + let range_count = doc_selection.ranges().len(); + + let selection = doc_selection.join_ranges(); + + doc.set_selection(view.id, selection); + cx.editor.set_status(format!( + "Joined {} range{}", + range_count, + if range_count == 1 { "" } else { "s" } + )); +} diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 3b70c7ff4973d..44e63aba2c690 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -129,7 +129,7 @@ pub fn default() -> HashMap { "^" => { "Selections" "s" => save_selection_to_register, "S" => restore_selection, - // "j" => join_selections, + "j" => join_selections, "c" => { "Combine selection from register" "a" => append_selection_from_register, "u" => union_selection_from_register, diff --git a/helix-term/tests/test/commands.rs b/helix-term/tests/test/commands.rs index e1a1e77015600..793d4d14d1a5f 100644 --- a/helix-term/tests/test/commands.rs +++ b/helix-term/tests/test/commands.rs @@ -198,3 +198,23 @@ async fn test_union_marker() -> anyhow::Result<()> { Ok(()) } + +#[tokio::test] +async fn test_join_selections() -> anyhow::Result<()> { + test(( + indoc! {"\ + #(foo|)# + bar + #[baz|]#" + }, + "^j", + indoc! {"\ + #[foo + bar + baz|]#" + }, + )) + .await?; + + Ok(()) +}