summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 16:40:06 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit2d1ae5034dfcfe9265689e7fa53c5a85b683a7a1 (patch)
treebcb6d6f1481fef311a7555007ef24e2e736674aa
parentbdbab17204efdb785b6ab3cc2022484485c0ded2 (diff)
downloadpardes-2d1ae5034dfcfe9265689e7fa53c5a85b683a7a1.tar.gz
pardes-2d1ae5034dfcfe9265689e7fa53c5a85b683a7a1.zip
Alt-u and Alt-U undo and redo
helix's earlier/later walk its history tree by time; pardes's history is a line, where earlier and later are undo and redo, so the keys are aliases. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--docs/helix-keys.md3
-rw-r--r--src/config.zig6
-rw-r--r--test/hxcases/cases.jsonl2
-rw-r--r--test/hxcases/goldens.jsonl2
4 files changed, 9 insertions, 4 deletions
diff --git a/docs/helix-keys.md b/docs/helix-keys.md
index 2928d78e..d2915cbb 100644
--- a/docs/helix-keys.md
+++ b/docs/helix-keys.md
@@ -118,7 +118,7 @@ language-backend queries, and the shell pipe.
| `d` | delete selection (implicit or explicit); bare cursor = the 1-wide selection | always yanks (`Alt-d` noyank in B); terminals: drops typed runs only | helix-verified |
| `c` | change (delete + insert mode); linewise selections open a fresh indented line | same shape as `d` | helix-verified |
| `y` | yank each range's text into the register (`"<reg>` names one, else `"`), one value per range | line-yank vim-ism removed (phase 5); yank keeps selection AND cursor (helix). The system clipboard is `"+y` / `SPC y`, helix's own split: a `d` of one character never clobbers what the desktop holds | helix-verified |
-| `u` / `U` | undo / redo | restores the pre-edit selection (helix); snapshot granularity, no `Alt-u`/`Alt-U` history walking (skipped) | helix-verified |
+| `u` / `U` | undo / redo | restores the pre-edit selection (helix); snapshot granularity, `Alt-u`/`Alt-U` are the same two: helix walks a history tree by time with them, and pardes's history is linear, so earlier and later ARE undo and redo | helix-verified |
| `p` (normal) | paste the register after each range: value i at range i, the last value repeated when there are fewer | helix `paste_impl`. `"+p` asks the system clipboard (`SPC p`); on a tty that read is OSC 52, which most terminals refuse: an honest no-op rather than a paste of the wrong text | helix-verified |
| `Esc` (body normal) | clear a pending modal prefix / exit select mode, keeping the selection, then run `Last`: hop to the pane you were in before this one, whichever kind it was, exactly like `SPC j j` — so held down it alternates between two panes, two files as readily as a file and its shell. A PDF pane is the ONE exception: there Esc is the document's own cancel (drop the mouse selection and the search overlay, stay where you are reading) and `Shift-Esc` is the hop out, while raw tty only intercepts unmodified Esc at a detected shell prompt | Pardes-specific focus binding layered on helix's cleanup. A leader path, tag, topbar or search owns Esc while it is active; raw tty forwards it | pardes-specific (cleanup helix-verified) |
| `Esc` (insert) | back to normal mode, cursor right after the insertion (no vim left-step) | | helix-verified |
@@ -357,7 +357,6 @@ text.
| `]g [g ]G [G` | git change jumps | needs VCS diff state |
| insert `Ctrl-x` | completion menu | completion exists, but not as a popup: insert-mode Tab straight after a `.` opens a buffer of candidate DECLARATIONS (section A). helix's menu itself is skipped |
| `Ctrl-s` (normal) | save jumplist position | jumplist itself is implemented (`Ctrl-o`/`Ctrl-i`, section A); only the explicit save point is skipped |
-| `Alt-u` / `Alt-U` | undo-history earlier/later | history timeline — linear snapshot u/U covers pardes |
| `:` | 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 |
diff --git a/src/config.zig b/src/config.zig
index 993b6fe0..80c08cce 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -569,8 +569,10 @@ pub const unindent: []const Chord = &.{.{ .cp = '<' }};
pub const format: []const Chord = &.{.{ .cp = '=' }};
pub const increment: []const Chord = &.{.{ .cp = 'a', .ctrl = true }};
pub const decrement: []const Chord = &.{.{ .cp = 'x', .ctrl = true }};
-pub const undo: []const Chord = &.{.{ .cp = 'u' }};
-pub const redo: []const Chord = &.{.{ .cp = 'U' }};
+// pardes's history is linear, so helix's earlier/later (Alt-u, Alt-U) are
+// undo and redo themselves
+pub const undo: []const Chord = &.{ .{ .cp = 'u' }, .{ .cp = 'u', .alt = true } };
+pub const redo: []const Chord = &.{ .{ .cp = 'U' }, .{ .cp = 'U', .alt = true } };
pub const comment_toggle: []const Chord = &.{.{ .cp = 'c', .ctrl = true }};
// Body-normal Esc runs Last; other modes cancel input or leave insert mode.
diff --git a/test/hxcases/cases.jsonl b/test/hxcases/cases.jsonl
index 03b20ff5..f23a8b2f 100644
--- a/test/hxcases/cases.jsonl
+++ b/test/hxcases/cases.jsonl
@@ -446,6 +446,8 @@
{"name": "goto-last-mod-delete", "pane": "file", "text": "abc\ndef\n", "keys": "jlxdgg"}
{"name": "goto-last-mod-delete-go", "pane": "file", "text": "abc\ndef\n", "keys": "jldggg."}
{"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": "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 8e642073..4c565b53 100644
--- a/test/hxcases/goldens.jsonl
+++ b/test/hxcases/goldens.jsonl
@@ -446,6 +446,8 @@
{"name":"goto-last-mod-delete","text":"abc\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
{"name":"goto-last-mod-delete-go","text":"abc\ndf\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}
{"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":"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}