summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/helix-keys.md2
-rw-r--r--src/edit.zig19
-rw-r--r--test/hxcases/cases.jsonl3
-rw-r--r--test/hxcases/goldens.jsonl3
4 files changed, 20 insertions, 7 deletions
diff --git a/docs/helix-keys.md b/docs/helix-keys.md
index 816010a6..f6880f33 100644
--- a/docs/helix-keys.md
+++ b/docs/helix-keys.md
@@ -301,7 +301,7 @@ keeps the matches it found so far.
| Key | Behavior | Notes | Status |
| --- | --- | --- | --- |
| `]p` / `[p` | next / prev paragraph (+ count) | helix `goto_next/prev_paragraph`: selects to the boundary (anchor at the origin), blank-line-delimited blocks, count iterates | helix-verified (phase 5) |
-| `]Space` / `[Space` | add `<n>` blank lines below / above, cursor staying on its text line | file panes only (shell output immutable) | helix-verified (phase 5) |
+| `]Space` / `[Space` | add `<n>` blank lines below the selection's last line / above its first, the selection staying on its text | file panes only (shell output immutable) | helix-verified (phase 5) |
### Insert mode
diff --git a/src/edit.zig b/src/edit.zig
index fb8681d8..b548c7c6 100644
--- a/src/edit.zig
+++ b/src/edit.zig
@@ -1452,9 +1452,12 @@ pub fn normalAdjustNumber(p: *Pardes, t: *Text, delta: i64) void {
/// `]Space` / `[Space`: add blank lines below/above, the cursor staying
/// on its text line (the selection rides along)
pub fn addNewline(p: *Pardes, t: *Text, below: bool, cnt: usize) void {
- const eb = editText(p, t, t.cur_row, t.cur_row, -1) orelse return;
+ // above the selection's first line, below its last (helix line_range)
+ const sr = selRows(t);
+ const at = if (below) sr.hi_row else sr.lo_row;
+ const eb = editText(p, t, at, at, -1) orelse return;
pushUndo(p, t);
- const row: usize = @intCast(@max(0, t.cur_row - eb.row0));
+ const row: usize = @intCast(@max(0, at - eb.row0));
const arena = p.scratch.allocator();
const nl = arena.alloc(u8, cnt) catch return;
@memset(nl, '\n');
@@ -1462,10 +1465,14 @@ pub fn addNewline(p: *Pardes, t: *Text, below: bool, cnt: usize) void {
const new = modal.insertAt(p.gpa, eb.text, .{ .row = row, .col = if (below) llen else 0 }, nl) catch return;
setEditText(p, t, new);
if (!below) {
- t.cur_row += @intCast(cnt); // the line moved down; stay on it
- if (t.vsel.active and t.vsel.row >= @as(i32, @intCast(row))) t.vsel.row += @intCast(cnt);
- } else if (t.vsel.active and t.vsel.row > @as(i32, @intCast(row))) {
- t.vsel.row += @intCast(cnt);
+ // the whole selection moved down; stay on it
+ const n: i32 = @intCast(cnt);
+ t.cur_row += n;
+ if (t.vsel.active) t.vsel.row += n;
+ if (t.msel.active) {
+ t.msel.r0 += n;
+ t.msel.r1 += n;
+ }
}
t.cur_pinned = true;
t.show();
diff --git a/test/hxcases/cases.jsonl b/test/hxcases/cases.jsonl
index 6e1b8188..ada7363b 100644
--- a/test/hxcases/cases.jsonl
+++ b/test/hxcases/cases.jsonl
@@ -252,6 +252,9 @@
{"name": "add-nl-below", "pane": "file", "text": "aa\nbb\n", "keys": "]<space>"}
{"name": "add-nl-above", "pane": "file", "text": "aa\nbb\n", "keys": "j[<space>"}
{"name": "add-nl-count", "pane": "file", "text": "aa\nbb\n", "keys": "2]<space>"}
+{"name": "add-nl-above-sel", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "vj[<space>"}
+{"name": "add-nl-below-sel", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "jvk]<space>"}
+{"name": "add-nl-above-lines", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "jxx[<space>"}
{"name": "d-word", "pane": "file", "text": "alpha beta\n", "keys": "wd"}
{"name": "d-bare-char", "pane": "file", "text": "abc\n", "keys": "d"}
{"name": "d-on-nl-joins", "pane": "file", "text": "ab\ncd\n", "keys": "lld"}
diff --git a/test/hxcases/goldens.jsonl b/test/hxcases/goldens.jsonl
index 8ac110e6..51ab8939 100644
--- a/test/hxcases/goldens.jsonl
+++ b/test/hxcases/goldens.jsonl
@@ -252,6 +252,9 @@
{"name":"add-nl-below","text":"aa\n\nbb\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
{"name":"add-nl-above","text":"aa\n\nbb\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}
{"name":"add-nl-count","text":"aa\n\n\nbb\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"add-nl-above-sel","text":"\naa\nbb\ncc\n","mode":"select","cursor":{"row":2,"col":0},"anchor":{"row":1,"col":0}}
+{"name":"add-nl-below-sel","text":"aa\nbb\n\ncc\n","mode":"select","cursor":{"row":0,"col":0},"anchor":{"row":1,"col":0}}
+{"name":"add-nl-above-lines","text":"aa\n\nbb\ncc\n","mode":"normal","cursor":{"row":3,"col":2},"anchor":{"row":2,"col":0}}
{"name":"d-word","text":"beta\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
{"name":"d-bare-char","text":"bc\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
{"name":"d-on-nl-joins","text":"abcd\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}