summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/helix-keys.md2
-rw-r--r--src/config.zig1
-rw-r--r--src/edit.zig2
-rw-r--r--test/hxcases/cases.jsonl4
-rw-r--r--test/hxcases/goldens.jsonl4
-rw-r--r--test/hxcases/waivers.jsonl1
6 files changed, 13 insertions, 1 deletions
diff --git a/docs/helix-keys.md b/docs/helix-keys.md
index d2915cbb..bb260802 100644
--- a/docs/helix-keys.md
+++ b/docs/helix-keys.md
@@ -341,6 +341,7 @@ text.
| `Home` / `End` | line start / line end past-the-last-char (`goto_line_end_newline`) | file panes (terminal insert cursor rides its run, as before) | helix-verified (phase 5) |
| `PageUp` / `PageDown` | cursor page up / down, col kept (clamped to line) | file panes | helix-verified (phase 5) |
| `Tab` | indent to the next 4-column stop with SPACES (`insertTab`, `edit.zig`: `pad = INDENT_W - col % INDENT_W`) — no `\t` byte ever reaches the file | helix's Spaces indent style; helix smart-tab skipped. After a `.` in a file the backend speaks, Tab instead asks for completion and only indents if the answer is empty (section A) | helix-verified (phase 5) |
+| insert `Ctrl-s` | commit an undo checkpoint: `u` after the session goes back to the text as it was here, a second `u` to before the session | helix `commit_undo_checkpoint`; a snapshot pushed mid-session | helix-verified |
## C. Skipped
@@ -360,7 +361,6 @@ text.
| `:` | command mode | side-effects/file-ops — pardes builtins live in the tag, and `:` is bound to focusing it (section A) |
| `gf` | goto file under selection | covered by pardes Enter-look |
| `Ctrl-z` | suspend | pardes IS the terminal multiplexer |
-| insert `Ctrl-s` | commit undo checkpoint | undo is per-insert-session snapshots; no sub-session checkpoints |
| `Shift-Tab` (insert), smart-tab semantics | insert tab / smart tab | smart-tab machinery; plain Tab-inserts-tab lands in B |
| `Z` (sticky view mode) | persistent view mode | marginal; `z` one-shots suffice |
| `zm` (view) | align middle horizontally | marginal even with hscroll |
diff --git a/src/config.zig b/src/config.zig
index 80c08cce..ecaa3357 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -582,6 +582,7 @@ pub const insert_backspace_alias: []const Chord = &.{.{ .cp = 'h', .ctrl = true
pub const insert_enter_alias: []const Chord = &.{.{ .cp = 'j', .ctrl = true }};
pub const insert_delete_alias: []const Chord = &.{.{ .cp = 'd', .ctrl = true }};
pub const insert_register: []const Chord = &.{.{ .cp = 'r', .ctrl = true }};
+pub const insert_checkpoint: []const Chord = &.{.{ .cp = 's', .ctrl = true }};
pub const delete_word_backward: []const Chord = &.{ .{ .cp = 'w', .ctrl = true }, .{ .cp = Key.backspace, .alt = true } };
pub const delete_word_forward: []const Chord = &.{ .{ .cp = 'd', .alt = true }, .{ .cp = Key.delete, .alt = true } };
pub const kill_to_line_start: []const Chord = &.{.{ .cp = 'u', .ctrl = true }};
diff --git a/src/edit.zig b/src/edit.zig
index 9398674a..39050b9d 100644
--- a/src/edit.zig
+++ b/src/edit.zig
@@ -656,6 +656,8 @@ pub fn insertKey(p: *Pardes, t: *Text, key: Key) void {
t.reg_wait = true;
return;
}
+ // helix commit_undo_checkpoint: `u` after the session goes back to here
+ if (hit(key, config.insert_checkpoint)) return pushUndo(p, t);
// helix maps every range through each insert-mode edit (Range::map):
// the edits below work on the bare cursor, and the range the cursor
// heads is carried through what they did to the text afterwards
diff --git a/test/hxcases/cases.jsonl b/test/hxcases/cases.jsonl
index f23a8b2f..15e53590 100644
--- a/test/hxcases/cases.jsonl
+++ b/test/hxcases/cases.jsonl
@@ -448,6 +448,10 @@
{"name": "goto-last-mod-select", "pane": "file", "text": "ab\ncd\nef\n", "keys": "jjiX<esc>ggvg."}
{"name": "alt-u-undo", "pane": "file", "text": "ab\n", "keys": "iX<esc><A-u>"}
{"name": "alt-U-redo", "pane": "file", "text": "ab\n", "keys": "iX<esc>u<A-U>"}
+{"name": "ins-checkpoint-undo", "pane": "file", "text": "ab\n", "keys": "iX<C-s>Y<esc>u"}
+{"name": "ins-checkpoint-undo-twice", "pane": "file", "text": "ab\n", "keys": "iX<C-s>Y<esc>uu"}
+{"name": "ins-checkpoint-redo", "pane": "file", "text": "ab\n", "keys": "iX<C-s>Y<esc>uuU"}
+{"name": "msel-ins-checkpoint", "pane": "file", "text": "ab\nab\n", "keys": "CiX<C-s>Y<esc>u"}
{"name": "msel-align-basic", "pane": "file", "text": "a=1\nbbb=2\n", "keys": "%s=<ret>&"}
{"name": "msel-align-columns", "pane": "file", "text": "a,b,c\nccc,d,e\n", "keys": "%s,<ret>&"}
{"name": "msel-align-uneven", "pane": "file", "text": "a,b\nccc,d,eee,f\n", "keys": "%s,<ret>&"}
diff --git a/test/hxcases/goldens.jsonl b/test/hxcases/goldens.jsonl
index 4c565b53..7a195980 100644
--- a/test/hxcases/goldens.jsonl
+++ b/test/hxcases/goldens.jsonl
@@ -448,6 +448,10 @@
{"name":"goto-last-mod-select","text":"ab\ncd\nXef\n","mode":"select","cursor":{"row":2,"col":1},"anchor":{"row":0,"col":0}}
{"name":"alt-u-undo","text":"ab\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
{"name":"alt-U-redo","text":"Xab\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}}
+{"name":"ins-checkpoint-undo","text":"Xab\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}}
+{"name":"ins-checkpoint-undo-twice","text":"ab\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"ins-checkpoint-redo","text":"Xab\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}}
+{"name":"msel-ins-checkpoint","text":"Xab\nXab\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
{"name":"msel-align-basic","text":"a =1\nbbb=2\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}},{"cursor":{"row":1,"col":3},"anchor":{"row":1,"col":3}}],"primary":0}
{"name":"msel-align-columns","text":"a ,b,c\nccc,d,e\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}},{"cursor":{"row":0,"col":5},"anchor":{"row":0,"col":5}},{"cursor":{"row":1,"col":3},"anchor":{"row":1,"col":3}},{"cursor":{"row":1,"col":5},"anchor":{"row":1,"col":5}}],"primary":0}
{"name":"msel-align-uneven","text":"a ,b\nccc,d,eee,f\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}},{"cursor":{"row":1,"col":3},"anchor":{"row":1,"col":3}},{"cursor":{"row":1,"col":5},"anchor":{"row":1,"col":5}},{"cursor":{"row":1,"col":9},"anchor":{"row":1,"col":9}}],"primary":0}
diff --git a/test/hxcases/waivers.jsonl b/test/hxcases/waivers.jsonl
index 2d74e346..6abc7de2 100644
--- a/test/hxcases/waivers.jsonl
+++ b/test/hxcases/waivers.jsonl
@@ -1 +1,2 @@
{"name":"alt-c-window-op","reason":"Alt-c moves a pane to a new column instead of Helix's change-noyank.","reference":{"name":"alt-c-window-op","text":"bc def\n","mode":"insert","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},"expected":{"name":"alt-c-window-op","text":"abc def\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}}
+{"name":"msel-ins-checkpoint","reason":"Undo restores the primary range alone: a history entry keeps one range, not every one, so the others stay where the edit left them.","reference":{"name":"msel-ins-checkpoint","text":"Xab\nXab\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1},"expected":{"name":"msel-ins-checkpoint","text":"Xab\nXab\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}}