Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keybind for Extend/shrink selection up and down #9080

Merged
merged 7 commits into from
Mar 17, 2024
57 changes: 56 additions & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use crate::{
use crate::job::{self, Jobs};
use futures_util::{stream::FuturesUnordered, TryStreamExt};
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
fmt,
future::Future,
Expand Down Expand Up @@ -298,6 +299,8 @@ impl MappableCommand {
extend_line, "Select current line, if already selected, extend to another line based on the anchor",
extend_line_below, "Select current line, if already selected, extend to next line",
extend_line_above, "Select current line, if already selected, extend to previous line",
select_line_above, "Select current line, if already selected, extend or shrink line above based on the anchor",
select_line_below, "Select current line, if already selected, extend or shrink line below based on the anchor",
extend_to_line_bounds, "Extend selection to line bounds",
shrink_to_line_bounds, "Shrink selection to line bounds",
delete_selection, "Delete selection",
Expand Down Expand Up @@ -2413,7 +2416,6 @@ fn extend_line_below(cx: &mut Context) {
fn extend_line_above(cx: &mut Context) {
extend_line_impl(cx, Extend::Above);
}
the-mikedavis marked this conversation as resolved.
Show resolved Hide resolved

fn extend_line_impl(cx: &mut Context, extend: Extend) {
let count = cx.count();
let (view, doc) = current!(cx.editor);
Expand Down Expand Up @@ -2452,6 +2454,59 @@ fn extend_line_impl(cx: &mut Context, extend: Extend) {

doc.set_selection(view.id, selection);
}
fn select_line_below(cx: &mut Context) {
select_line_impl(cx, Extend::Below);
}
fn select_line_above(cx: &mut Context) {
select_line_impl(cx, Extend::Above);
}
fn select_line_impl(cx: &mut Context, extend: Extend) {
let mut count = cx.count();
let (view, doc) = current!(cx.editor);
let text = doc.text();
let saturating_add = |a: usize, b: usize| (a + b).min(text.len_lines());
let selection = doc.selection(view.id).clone().transform(|range| {
let (start_line, end_line) = range.line_range(text.slice(..));
let start = text.line_to_char(start_line);
let end = text.line_to_char(saturating_add(end_line, 1));
let direction = range.direction();

// Extending to line bounds is counted as one step
if range.from() != start || range.to() != end {
count = count.saturating_sub(1)
}
let (anchor_line, head_line) = match (&extend, direction) {
(Extend::Above, Direction::Forward) => (start_line, end_line.saturating_sub(count)),
(Extend::Above, Direction::Backward) => (end_line, start_line.saturating_sub(count)),
(Extend::Below, Direction::Forward) => (start_line, saturating_add(end_line, count)),
(Extend::Below, Direction::Backward) => (end_line, saturating_add(start_line, count)),
};
let (anchor, head) = match anchor_line.cmp(&head_line) {
Ordering::Less => (
text.line_to_char(anchor_line),
text.line_to_char(saturating_add(head_line, 1)),
),
Ordering::Equal => match extend {
Extend::Above => (
text.line_to_char(saturating_add(anchor_line, 1)),
text.line_to_char(head_line),
),
Extend::Below => (
text.line_to_char(head_line),
text.line_to_char(saturating_add(anchor_line, 1)),
),
},

Ordering::Greater => (
text.line_to_char(saturating_add(anchor_line, 1)),
text.line_to_char(head_line),
),
};
Range::new(anchor, head)
});

doc.set_selection(view.id, selection);
}

fn extend_to_line_bounds(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
Expand Down
Loading