From 24aeefed99c821d42ed7c9cb556011a99d434ebd Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Sun, 25 Jun 2023 13:50:37 -0400 Subject: [PATCH] feat(command): select_all_children_in_selection --- helix-term/src/commands.rs | 53 ++++++++++++++-------- helix-term/tests/test/commands/movement.rs | 40 ++++++++-------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 248b94202d4e..83f8c269099f 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -33,6 +33,7 @@ use helix_core::{ syntax::{BlockCommentToken, LanguageServerFeature}, text_annotations::{Overlay, TextAnnotations}, textobject, + tree_sitter::Tree, unicode::width::UnicodeWidthChar, visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes, RopeReader, RopeSlice, Selection, SmallVec, Tendril, Transaction, @@ -439,6 +440,7 @@ impl MappableCommand { select_prev_sibling, "Select previous sibling the in syntax tree", select_all_siblings, "Select all siblings of the current node", select_all_children, "Select all children of the current node", + select_all_children_in_selection, "Select all children of the current node that are contained in the current selection", jump_forward, "Jump forward on jumplist", jump_backward, "Jump backward on jumplist", save_selection, "Save current selection to jumplist", @@ -4943,17 +4945,39 @@ pub fn extend_parent_node_start(cx: &mut Context) { move_node_bound_impl(cx, Direction::Backward, Movement::Extend) } +fn select_all_impl(editor: &mut Editor, select_fn: F) +where + F: Fn(&Tree, RopeSlice, Selection) -> Selection, +{ + let (view, doc) = current!(editor); + + if let Some(syntax) = doc.syntax() { + let text = doc.text().slice(..); + let current_selection = doc.selection(view.id); + let selection = select_fn(syntax.tree(), text, current_selection.clone()); + doc.set_selection(view.id, selection); + } +} + fn select_all_siblings(cx: &mut Context) { let motion = |editor: &mut Editor| { - let (view, doc) = current!(editor); + select_all_impl(editor, object::select_all_siblings); + }; - if let Some(syntax) = doc.syntax() { - let text = doc.text().slice(..); - let current_selection = doc.selection(view.id); - let selection = - object::select_all_siblings(syntax.tree(), text, current_selection.clone()); - doc.set_selection(view.id, selection); - } + cx.editor.apply_motion(motion); +} + +fn select_all_children_in_selection(cx: &mut Context) { + let motion = |editor: &mut Editor| { + select_all_impl(editor, |tree, text, selection| { + let all_children = object::select_all_children(tree, text, selection.clone()); + + if selection.contains(&all_children) { + all_children + } else { + selection + } + }); }; cx.editor.apply_motion(motion); @@ -4961,19 +4985,10 @@ fn select_all_siblings(cx: &mut Context) { fn select_all_children(cx: &mut Context) { let motion = |editor: &mut Editor| { - let (view, doc) = current!(editor); - - if let Some(syntax) = doc.syntax() { - let text = doc.text().slice(..); - let current_selection = doc.selection(view.id); - let selection = - object::select_all_children(syntax.tree(), text, current_selection.clone()); - doc.set_selection(view.id, selection); - } + select_all_impl(editor, object::select_all_children); }; - motion(cx.editor); - cx.editor.last_motion = Some(Motion(Box::new(motion))); + cx.editor.apply_motion(motion); } fn match_brackets(cx: &mut Context) { diff --git a/helix-term/tests/test/commands/movement.rs b/helix-term/tests/test/commands/movement.rs index 84806d5f8b8f..1f33b3944200 100644 --- a/helix-term/tests/test/commands/movement.rs +++ b/helix-term/tests/test/commands/movement.rs @@ -607,16 +607,16 @@ async fn select_all_children() -> anyhow::Result<()> { let tests = vec![ // basic tests ( - helpers::platform_line(indoc! {r##" + indoc! {r##" let foo = bar#[(a, b, c)|]#; - "##}), + "##}, "", - helpers::platform_line(indoc! {r##" + indoc! {r##" let foo = bar(#[a|]#, #(b|)#, #(c|)#); - "##}), + "##}, ), ( - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = #[[ 1, 2, @@ -624,9 +624,9 @@ async fn select_all_children() -> anyhow::Result<()> { 4, 5, ]|]#; - "##}), + "##}, "", - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = [ #[1|]#, #(2|)#, @@ -634,11 +634,11 @@ async fn select_all_children() -> anyhow::Result<()> { #(4|)#, #(5|)#, ]; - "##}), + "##}, ), // direction is preserved ( - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = #[|[ 1, 2, @@ -646,9 +646,9 @@ async fn select_all_children() -> anyhow::Result<()> { 4, 5, ]]#; - "##}), + "##}, "", - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = [ #[|1]#, #(|2)#, @@ -656,11 +656,11 @@ async fn select_all_children() -> anyhow::Result<()> { #(|4)#, #(|5)#, ]; - "##}), + "##}, ), // can't pick any more children - selection stays the same ( - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = [ #[1|]#, #(2|)#, @@ -668,9 +668,9 @@ async fn select_all_children() -> anyhow::Result<()> { #(4|)#, #(5|)#, ]; - "##}), + "##}, "", - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = [ #[1|]#, #(2|)#, @@ -678,11 +678,11 @@ async fn select_all_children() -> anyhow::Result<()> { #(4|)#, #(5|)#, ]; - "##}), + "##}, ), // each cursor does the sibling select independently ( - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = #[|[ 1, 2, @@ -698,9 +698,9 @@ async fn select_all_children() -> anyhow::Result<()> { "four", "five", ]|)#; - "##}), + "##}, "", - helpers::platform_line(indoc! {r##" + indoc! {r##" let a = [ #[|1]#, #(|2)#, @@ -716,7 +716,7 @@ async fn select_all_children() -> anyhow::Result<()> { #("four"|)#, #("five"|)#, ]; - "##}), + "##}, ), ];