diff options
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r-- | helix-term/src/commands.rs | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index bf12b122..5c26a5b2 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -362,6 +362,7 @@ impl MappableCommand { rotate_selection_contents_forward, "Rotate selection contents forward", rotate_selection_contents_backward, "Rotate selections contents backward", expand_selection, "Expand selection to parent syntax node", + shrink_selection, "Shrink selection to previously expanded syntax node", jump_forward, "Jump forward on jumplist", jump_backward, "Jump backward on jumplist", save_selection, "Save the current selection to the jumplist", @@ -5467,6 +5468,7 @@ fn rotate_selection_contents(cx: &mut Context, direction: Direction) { doc.apply(&transaction, view.id); doc.append_changes_to_history(view.id); } + fn rotate_selection_contents_forward(cx: &mut Context) { rotate_selection_contents(cx, Direction::Forward) } @@ -5482,7 +5484,39 @@ fn expand_selection(cx: &mut Context) { if let Some(syntax) = doc.syntax() { let text = doc.text().slice(..); - let selection = object::expand_selection(syntax, text, doc.selection(view.id)); + + let current_selection = doc.selection(view.id); + + // save current selection so it can be restored using shrink_selection + view.object_selections.push(current_selection.clone()); + + let selection = object::expand_selection(syntax, text, current_selection); + doc.set_selection(view.id, selection); + } + }; + motion(cx.editor); + cx.editor.last_motion = Some(Motion(Box::new(motion))); +} + +fn shrink_selection(cx: &mut Context) { + let motion = |editor: &mut Editor| { + let (view, doc) = current!(editor); + let current_selection = doc.selection(view.id); + // try to restore previous selection + if let Some(prev_selection) = view.object_selections.pop() { + if current_selection.contains(&prev_selection) { + // allow shrinking the selection only if current selection contains the previous object selection + doc.set_selection(view.id, prev_selection); + return; + } else { + // clear existing selection as they can't be shrinked to anyway + view.object_selections.clear(); + } + } + // if not previous selection, shrink to first child + if let Some(syntax) = doc.syntax() { + let text = doc.text().slice(..); + let selection = object::shrink_selection(syntax, text, current_selection); doc.set_selection(view.id, selection); } }; |