Keybind for Extend/shrink selection up and down (#9080)
* implement another selection modifying command * Selection feels more ergonomic in case of swapping the direction. This also fixes a problem when starting at an empty line. * rename select_line_up/down to select_line_above/below * apply clippy suggestion of using cmp instead of if-chain * revert `Extent` implementing `Clone/Copy` * move select_line functions below extend_line implementations * implement help add function, which saturates at the number of text lines --------- Co-authored-by: Emi <emanuel.boehm@gmail.com>
This commit is contained in:
parent
6fea7876a4
commit
761df60077
1 changed files with 56 additions and 1 deletions
|
@ -57,6 +57,7 @@ use crate::{
|
|||
|
||||
use crate::job::{self, Jobs};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
future::Future,
|
||||
|
@ -300,6 +301,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",
|
||||
|
@ -2435,7 +2438,6 @@ fn extend_line_below(cx: &mut Context) {
|
|||
fn extend_line_above(cx: &mut Context) {
|
||||
extend_line_impl(cx, Extend::Above);
|
||||
}
|
||||
|
||||
fn extend_line_impl(cx: &mut Context, extend: Extend) {
|
||||
let count = cx.count();
|
||||
let (view, doc) = current!(cx.editor);
|
||||
|
@ -2474,6 +2476,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);
|
||||
|
|
Loading…
Add table
Reference in a new issue