diff options
Diffstat (limited to 'docs/helix-keys.md')
| -rw-r--r-- | docs/helix-keys.md | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/docs/helix-keys.md b/docs/helix-keys.md index 81bc0248..dcd5b7cb 100644 --- a/docs/helix-keys.md +++ b/docs/helix-keys.md @@ -13,21 +13,20 @@ single key — it is the anchor-only divergence every insert-mode edit shares � and is described in the Files list at the bottom instead. Code map, by SYMBOL — line numbers rot, names do not. Body-normal key -RECOGNITION is `src/normal_input.zig`: a pure state machine over `Role` (one +RECOGNITION is `modal.Normal` in `src/modal.zig`: a state machine over `Role` (one per bound command, matched against `src/config.zig`'s chord lists by `Pardes.normalInput`), a `Prefix`, a `MatchSub` and a count, emitting a semantic `Action` that both the text and PDF adapters consume. It knows nothing about panes or text. `src/pardes.zig` then EXECUTES: `Key`, `handleKey` (intercept order is load-bearing, see the comment there), -`handleNormal` (marshals `Pane`'s compact fields in and out of -`normal_input.State` through `paneNormalState` / `putPaneNormalState`), +`handleNormal` (parses directly into `Pane.normal`), `executeNormalAction`, `setPaneRange` (helix range → pane state), `enterInsert`, `handleInsert` / `insertKey`, `insertTab`, `normalDelete`, -`normalYank`, `normalPaste`, `normalChange`, `replaySels`, `multiOnce`. Undo -and redo are per pane kind, in `file_pane` and `term_pane`. Pure text math: +`normalYank`, `pasteText`, `normalChange`, `replaySels`, `multiOnce`. Undo +and redo live in `panes.File` and `panes.Terminal`. Pure text math: `src/modal.zig` (the `hx*` family is the helix-semantics layer: gap offsets + ranges over the flat text). Differential harness: `test/hxdiff.zig` + -`test/hxcases/*.jsonl` + `test/hxcases/regen.sh` — see "Differential testing" +`test/hxcases/*.jsonl` — see "Differential testing" at the bottom. ## Global semantic divergences (read first) @@ -94,7 +93,7 @@ language-backend queries, and the shell pipe. | `w` `b` `e` | select to next word start / prev word start / next word end | full helix model incl. landing conventions (block cursor one before the next word after `w`) and newline/punct/EOF edges | helix-verified | | `W` `B` `E` | long-word (WORD) variants | same | helix-verified | | `Home` / `End` | line start / line end | matches `goto_line_start` / `goto_line_end` | helix-verified | -| `0` / `$` / `^` | line start / line end / first non-ws | `0` and `^` are pardes extras — helix leaves those two unbound (it spells them `gh`/`gs`). `$` is NOT unbound in helix: it is `shell_keep_pipe` (`keymap/default.rs`), and taking it for line-end is a deliberate divergence — see the `$` row in C. `0` is a count digit while a count is pending | pardes-specific (`$`: deliberate) | +| `0` / `$` / `^` | line start / line end / first non-ws | `0` and `^` are pardes extras — helix leaves those two unbound (it spells them `gh`/`gs`). `$` is NOT unbound in helix: it is `shell_keep_pipe` (`keymap/default.rs`), and taking it for line-end is a deliberate divergence — see the `$` row in C. It is the one shell command still unimplemented: it needs a per-selection verdict, where the runner's answer is atomic. `0` is a count digit while a count is pending | pardes-specific (`$`: deliberate) | | `G` | bare `G` is a **no-op**; `<n>G` = goto line n | vim-ism removed (phase 5): helix `goto_line` only acts with a count; `ge` is goto-last-line | helix-verified | | `gg` / `<n>gg` | goto first line / line n | | helix-verified | | `ge` | goto last content line | matches `goto_last_line` (ignores the trailing empty line) | helix-verified | @@ -137,6 +136,9 @@ language-backend queries, and the shell pipe. | `=` | `format_selections` — writes a `- old` / `+ new` diff into `+Lsp` | deliberate divergence: the seam returns ROWS, not edits, so this SHOWS the formatting instead of applying it. Not in the corpus, so there is no waiver to name — the query leaves the core as an effect the headless harness has no shell to perform | out of corpus | | `Ctrl-o` / `Ctrl-i` | jumplist back / forward — the `Back` / `Forward` builtins, also on `SPC j o` / `SPC j i`, with `SPC j l` rendering the stack as a buffer | helix binds both keys (`jump_backward` / `jump_forward`) but to a POSITION jumplist; pardes' stack is over panes and focus, so the keys agree and the semantics do not. `Ctrl-i` and Tab are the same byte under the legacy encoding; there Tab keeps meaning execute, and the pair only separates where the host speaks the kitty keyboard protocol | pardes-specific | | `\|` | pipe every selection through `/bin/sh -c`: its bytes in on stdin, its stdout replacing them, one undo across all cursors | helix's own key and meaning; the command is typed into the pane's tag after a bare `\|` marker rather than into a popup | out of corpus | +| `A-\|` | the same, and the output is DISCARDED — the text is not touched at all | helix `shell_pipe_to`. For a command run for its effect. Marker `\|-` | out of corpus | +| `!` | run with NO stdin, insert the output BEFORE each selection | helix `shell_insert_output`. Runs ONCE and every cursor gets that one answer, as helix does — ten cursors and `date` give ten identical stamps. Marker `!` | out of corpus | +| `A-!` | the same, appended AFTER each selection | helix `shell_append_output`. Marker `!+` | out of corpus | ## B. To implement @@ -144,13 +146,10 @@ Status: `todo` → set to `done (phase N)` as rows land. All rows verified against keymap.md. Edit ops on terminal panes obey the immutable-output rule (typed runs only) — same as `d`/`c` today. -Phase 2's recognition state is now `normal_input.State`: a count (accumulator, +`Pane.normal` holds `modal.Normal.State`: a count (accumulator, capped 0xffff), a `Prefix` (`g` `z` `m` `f` `F` `t` `T` `r` `]` `[`), a `MatchSub` (m-mode's `i`/`a`/`s`/`r`/`d`) and one `held_char` for `mr`'s -`<from>`. `Pane` keeps the same four fields it always did — `count`, -`pending`, `pending2`, `pending_ch` — but purely as compact per-pane storage, -marshalled in and out by `paneNormalState` / `putPaneNormalState`; the -comments on them say so. `find_op`/`find_ch` (the `Alt-.` repeat target) stay +`<from>`. `find_op`/`find_ch` (the `Alt-.` repeat target) stay on `Pane`, because the parser emits `repeat_find` without remembering what was found. Pure text math in `modal.zig`: `findChar`, `matchBracket`, `paragraphFwd`/`paragraphBwd`/`paragraphRange`, textobject/surround ranges, @@ -376,7 +375,7 @@ Files (all in `test/hxcases/`): immutable) or doc-marked terminal no-ops. tty case texts keep motions inside the content (the tty motion surface trims trailing blank rows, so ge/G-to-last-line style assertions stay off tty). -- `goldens.jsonl` — checked-in helix results, regenerated by `regen.sh` +- `goldens.jsonl` — checked-in helix results, regenerated by `zig build hxdiff-update` (runs the `hx-harness` binary from the helix checkout; override with `$HX_HARNESS`). Only needed when cases change — the diff itself runs offline. @@ -414,7 +413,11 @@ Run it: # "editing a shell pane behaves like editing a # file" cannot drift. The case's own "pane" field # is ignored; exemptions in parity-waivers.jsonl - sh test/hxcases/regen.sh # regenerate goldens + zig build hxdiff-live # compare a fresh reference without changing goldens + zig build hxdiff-update # update goldens only after the live comparison passes + +Set `-Dhelix-harness=/path/to/hx-harness` or `HX_HARNESS`; otherwise these +steps look for `hx-harness` on PATH. The helix half (`hx-harness`) lives on the `pardes-harness` branch: a full headless `Application` with LSP/tree-sitter/auto-pairs/word- |
