changeset 6701:c669fff516c7

Add support for extend_file_{start,end} (#11767)
author Dimitri Sabadie <hadronized@strongly-typed-thoughts.net>
date Sun, 06 Apr 2025 20:18:47 +0200
parents 1e2d84240390
children f05a3d9ba708
files book/src/generated/static-cmd.md helix-term/src/commands.rs helix-term/src/commands/typed.rs helix-term/src/keymap/default.rs
diffstat 4 files changed, 58 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/book/src/generated/static-cmd.md	Sun Apr 06 20:00:18 2025 +0200
+++ b/book/src/generated/static-cmd.md	Sun Apr 06 20:18:47 2025 +0200
@@ -126,8 +126,10 @@
 | `add_newline_below` | Add newline below | normal: `` ]<space> ``, select: `` ]<space> `` |
 | `goto_type_definition` | Goto type definition | normal: `` gy ``, select: `` gy `` |
 | `goto_implementation` | Goto implementation | normal: `` gi ``, select: `` gi `` |
-| `goto_file_start` | Goto line number <n> else file start | normal: `` gg ``, select: `` gg `` |
+| `goto_file_start` | Goto line number <n> else file start | normal: `` gg `` |
 | `goto_file_end` | Goto file end |  |
+| `extend_to_file_start` | Extend to line number<n> else file start | select: `` gg `` |
+| `extend_to_file_end` | Extend to file end |  |
 | `goto_file` | Goto files/URLs in selections | normal: `` gf ``, select: `` gf `` |
 | `goto_file_hsplit` | Goto files in selections (hsplit) | normal: `` <C-w>f ``, `` <space>wf ``, select: `` <C-w>f ``, `` <space>wf `` |
 | `goto_file_vsplit` | Goto files in selections (vsplit) | normal: `` <C-w>F ``, `` <space>wF ``, select: `` <C-w>F ``, `` <space>wF `` |
@@ -139,7 +141,8 @@
 | `goto_last_modified_file` | Goto last modified file | normal: `` gm ``, select: `` gm `` |
 | `goto_last_modification` | Goto last modification | normal: `` g. ``, select: `` g. `` |
 | `goto_line` | Goto line | normal: `` G ``, select: `` G `` |
-| `goto_last_line` | Goto last line | normal: `` ge ``, select: `` ge `` |
+| `goto_last_line` | Goto last line | normal: `` ge `` |
+| `extend_to_last_line` | Extend to last line | select: `` ge `` |
 | `goto_first_diag` | Goto first diagnostic | normal: `` [D ``, select: `` [D `` |
 | `goto_last_diag` | Goto last diagnostic | normal: `` ]D ``, select: `` ]D `` |
 | `goto_next_diag` | Goto next diagnostic | normal: `` ]d ``, select: `` ]d `` |
--- a/helix-term/src/commands.rs	Sun Apr 06 20:00:18 2025 +0200
+++ b/helix-term/src/commands.rs	Sun Apr 06 20:18:47 2025 +0200
@@ -426,6 +426,8 @@
         goto_implementation, "Goto implementation",
         goto_file_start, "Goto line number <n> else file start",
         goto_file_end, "Goto file end",
+        extend_to_file_start, "Extend to line number<n> else file start",
+        extend_to_file_end, "Extend to file end",
         goto_file, "Goto files/URLs in selections",
         goto_file_hsplit, "Goto files in selections (hsplit)",
         goto_file_vsplit, "Goto files in selections (vsplit)",
@@ -438,6 +440,7 @@
         goto_last_modification, "Goto last modification",
         goto_line, "Goto line",
         goto_last_line, "Goto last line",
+        extend_to_last_line, "Extend to last line",
         goto_first_diag, "Goto first diagnostic",
         goto_last_diag, "Goto last diagnostic",
         goto_next_diag, "Goto next diagnostic",
@@ -1253,28 +1256,44 @@
 }
 
 fn goto_file_start(cx: &mut Context) {
+    goto_file_start_impl(cx, Movement::Move);
+}
+
+fn extend_to_file_start(cx: &mut Context) {
+    goto_file_start_impl(cx, Movement::Extend);
+}
+
+fn goto_file_start_impl(cx: &mut Context, movement: Movement) {
     if cx.count.is_some() {
-        goto_line(cx);
+        goto_line_impl(cx, movement);
     } else {
         let (view, doc) = current!(cx.editor);
         let text = doc.text().slice(..);
         let selection = doc
             .selection(view.id)
             .clone()
-            .transform(|range| range.put_cursor(text, 0, cx.editor.mode == Mode::Select));
+            .transform(|range| range.put_cursor(text, 0, movement == Movement::Extend));
         push_jump(view, doc);
         doc.set_selection(view.id, selection);
     }
 }
 
 fn goto_file_end(cx: &mut Context) {
+    goto_file_end_impl(cx, Movement::Move);
+}
+
+fn extend_to_file_end(cx: &mut Context) {
+    goto_file_end_impl(cx, Movement::Extend)
+}
+
+fn goto_file_end_impl(cx: &mut Context, movement: Movement) {
     let (view, doc) = current!(cx.editor);
     let text = doc.text().slice(..);
     let pos = doc.text().len_chars();
     let selection = doc
         .selection(view.id)
         .clone()
-        .transform(|range| range.put_cursor(text, pos, cx.editor.mode == Mode::Select));
+        .transform(|range| range.put_cursor(text, pos, movement == Movement::Extend));
     push_jump(view, doc);
     doc.set_selection(view.id, selection);
 }
@@ -3746,15 +3765,23 @@
 }
 
 fn goto_line(cx: &mut Context) {
+    goto_line_impl(cx, Movement::Move);
+}
+
+fn goto_line_impl(cx: &mut Context, movement: Movement) {
     if cx.count.is_some() {
         let (view, doc) = current!(cx.editor);
         push_jump(view, doc);
 
-        goto_line_without_jumplist(cx.editor, cx.count);
+        goto_line_without_jumplist(cx.editor, cx.count, movement);
     }
 }
 
-fn goto_line_without_jumplist(editor: &mut Editor, count: Option<NonZeroUsize>) {
+fn goto_line_without_jumplist(
+    editor: &mut Editor,
+    count: Option<NonZeroUsize>,
+    movement: Movement,
+) {
     if let Some(count) = count {
         let (view, doc) = current!(editor);
         let text = doc.text().slice(..);
@@ -3769,13 +3796,21 @@
         let selection = doc
             .selection(view.id)
             .clone()
-            .transform(|range| range.put_cursor(text, pos, editor.mode == Mode::Select));
+            .transform(|range| range.put_cursor(text, pos, movement == Movement::Extend));
 
         doc.set_selection(view.id, selection);
     }
 }
 
 fn goto_last_line(cx: &mut Context) {
+    goto_last_line_impl(cx, Movement::Move)
+}
+
+fn extend_to_last_line(cx: &mut Context) {
+    goto_last_line_impl(cx, Movement::Extend)
+}
+
+fn goto_last_line_impl(cx: &mut Context, movement: Movement) {
     let (view, doc) = current!(cx.editor);
     let text = doc.text().slice(..);
     let line_idx = if text.line(text.len_lines() - 1).len_chars() == 0 {
@@ -3788,7 +3823,7 @@
     let selection = doc
         .selection(view.id)
         .clone()
-        .transform(|range| range.put_cursor(text, pos, cx.editor.mode == Mode::Select));
+        .transform(|range| range.put_cursor(text, pos, movement == Movement::Extend));
 
     push_jump(view, doc);
     doc.set_selection(view.id, selection);
--- a/helix-term/src/commands/typed.rs	Sun Apr 06 20:00:18 2025 +0200
+++ b/helix-term/src/commands/typed.rs	Sun Apr 06 20:18:47 2025 +0200
@@ -1880,7 +1880,15 @@
 
     let scrolloff = cx.editor.config().scrolloff;
     let line = args[0].parse::<usize>()?;
-    goto_line_without_jumplist(cx.editor, NonZeroUsize::new(line));
+    goto_line_without_jumplist(
+        cx.editor,
+        NonZeroUsize::new(line),
+        if cx.editor.mode == Mode::Select {
+            Movement::Extend
+        } else {
+            Movement::Move
+        },
+    );
 
     let (view, doc) = current!(cx.editor);
     view.ensure_cursor_in_view(doc, scrolloff);
--- a/helix-term/src/keymap/default.rs	Sun Apr 06 20:00:18 2025 +0200
+++ b/helix-term/src/keymap/default.rs	Sun Apr 06 20:18:47 2025 +0200
@@ -367,6 +367,8 @@
 
         "v" => normal_mode,
         "g" => { "Goto"
+            "g" => extend_to_file_start,
+            "e" => extend_to_last_line,
             "k" => extend_line_up,
             "j" => extend_line_down,
             "w" => extend_to_word,