summaryrefslogtreecommitdiff
path: root/test/snapshots/leader.snap
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-29 10:20:50 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:07 -0300
commitcc173a821bd6fd84fa6e7c2f272b7e049c7a1aaa (patch)
tree23dadf74493c0172ea7fced1dff44d2a4178c752 /test/snapshots/leader.snap
parent4e642c1d6688baf3b98f269818b66cc7cc194c5f (diff)
downloadpardes-cc173a821bd6fd84fa6e7c2f272b7e049c7a1aaa.tar.gz
pardes-cc173a821bd6fd84fa6e7c2f272b7e049c7a1aaa.zip
lsp: writer seam, ZLS introspection builtins, ctrl-click goto, SPC l group
THE SEAM TAKES A WRITER. `lsp.query`'s `out` is a `*std.Io.Writer`, not a `*std.ArrayList(u8)`. The shell owns the buffer behind it (an `Io.Writer.Allocating`), so a backend never allocates the result, never frees it, and cannot get the allocator wrong — the invalid-free class of bug has nowhere left to live. It also deleted a parameter from five functions: they only ever took a `gpa` to allocate rows, and 0.16's unused-parameter error found every one. `lsp.row()` lost its allocator argument too. Since a Writer cannot rewind or be counted, `query` renders into a scratch Allocating first: the log wants an exact row count, and `explain` throws the rows away and prints narration in their place. INTROSPECTION. `SPC l i` (Lspinfo) and `SPC l w` (Lspwhy), in the `l` group that now holds every language command (see below). They exist because of the seam's own contract: a backend never fails loudly, which is right for an editor, but it makes a broken backend and a correct one that found nothing look identical from the outside. Every query now leaves a record — kind, file, offset, duration, row count, and THE ERROR `run` returned, which `catch {}` swallowed and which was visible nowhere. Lspinfo prints those, plus which ZLS is compiled in, which zig lib dir and whether it actually opens (the usual cause of "gd does nothing in std"), and what the backend answers versus refuses. It answers from ANY pane, including one with no file, because it is about the backend — which matters precisely when the pane you are sitting in is the problem; both shells now send status for a file-less pane. Lspwhy narrates the REAL resolution path. The trace is threaded through `goto` itself, so what it prints is the position context the analyser returned and the branch that actually stopped. A debug view that re-derives the logic beside it is one that can disagree with it. CTRL-CLICK IS gd. Mouse gained a `ctrl` field, set by both shells (SDL asked directly via GetModState rather than read off key-event bookkeeping, which a click with no prior keypress would miss). The flag rides the drag rather than firing on the press: a click does not place the modal cursor until RELEASE, so a query asked at press time would answer about wherever the cursor previously sat. A ctrl-DRAG still selects. The snapshot DSL gained a `ctrl-` button prefix (SGR bit 4, what a terminal sends and what vaxis decodes). test/snapshots/lspdebug.snap covers all three, including a PLAIN click in the same spot that must NOT jump — without it the test would pass on a bug that made every click a goto. Durations cannot live in a golden, so PARDES_LSP_NOTIME (set by the harness, like PARDES_DUMP) omits them. 58 snapshot scripts, hxdiff 360, hxparity 440, unit 46, gui build: all green. lspbench: 17/17, 0 false claims. THE WHOLE LANGUAGE GROUP LIVES UNDER SPC l. pardes keeps its own leader letters back. `SPC d` is Del again, `SPC k` is Kill, `SPC s d`/`SPC s r` are Dump/Restore and `SPC h t` is Tutor — exactly where they were before the language work touched them. The previous pass put the LSP commands on helix's bare `<space>` letters and moved pardes's builtins out of the way (Kill k->q, Del d->wc, Dump/Restore s?->f?, Tutor ht->T). That was the wrong trade. Those five are the most-pressed keys in the editor and predate the language work; an LSP command is something you reach for deliberately and can afford one keystroke more. So every LSP command keeps HELIX'S OWN LETTER and gains the `l` prefix: `<space>k` -> `SPC l k` (hover), `<space>d` -> `SPC l d` (diagnostics), r/a/h/s/S/D likewise. Nothing to re-learn but the prefix, and `Lspinfo`/ `Lspwhy` were already there. THE GOTOS ARE UNTOUCHED. `gd` `gD` `gy` `gi` `gr`, `]d`/`[d`, `]D`/`[D`, `=` and ctrl-click all stay exactly as helix has them — they never collided with anything, so there was never a reason to move them, and they are the ones you actually press mid-edit. leader.snap is restored to the pre-LSP script (its `key q` unmapped-key step works again now that Kill is back on `k`) plus one new step for `SPC l ?`. Its `SPC ?` root listing had to stop waiting on Restore: the full list grew to 33 rows and row 21 falls off the pane, so it watches an early row instead. DEPENDENCY IMPORTS NOW RESOLVE. `gd` on `@import("vaxis")` opens vaxis's root file; before, it silently did nothing while `std` worked perfectly. The asymmetry was not a wiring mistake. ZLS's uriFromImportStr answers exactly three ways: a relative `.zig`/`.zon` path from disk, `std` from `zig_lib_dir` (one directory, which we supply), and EVERY OTHER NAME only by running `zig build --build-runner` to discover the module graph. That last branch needs `zig_exe_path`, which this backend sets to null on purpose — so every dependency import returned `.none`. Confirmed twice over: in ZLS's source, and by `SPC l w` on the import string, which printed the STOP line naming exactly that branch. (The introspection builtin diagnosing its own backend on its first real outing is a decent argument for having built it.) We never needed a compiler for this: build.zig IS the module graph. It folds `root_mod.import_table` into a name -> root-source-file table at configure time and passes it as a build option; the backend consults it precisely where ZLS gave up. Correct by construction — a dependency added or renamed in build.zig cannot forget to update it — and it costs no subprocess, no build step and no runtime work. `SPC l i` now lists the table, since "is this name even importable" is the first question when a jump does nothing. Two limits, both stated in the code: a module whose root is a GENERATED file is skipped (it has no path until make() runs), and a file inside a dependency importing that dependency's OWN internal module name is still a miss — that would mean running its build.zig. TRAP: the table is folded out of root_mod.import_table, so `addOptions` had to move BELOW every `addImport` call. Attached where it was, the table is empty. TOPBAR GAINS `Help`, WHICH IS WHY `SPC ?` LOOKED BROKEN. A bare `pardes` boots straight into tty mode (main.zig: `args.len == 1`), where every printable key belongs to the shell — so SPC never reaches the leader, and `SPC ?`, the one thing that would tell you the leader exists, is exactly the thing you cannot press. Ctrl-b first and it all works; nothing was broken. But "the help is unreachable until you already know the escape hatch" is a bad answer, and there was no mouse route either: Help was the one builtin missing from the bar. Row 0 is not a pane, so a middle-click there is dispatched before any pane's mode is consulted — the word works in tty mode, which is the only reason it earns the width. APPENDED, not inserted, so every existing topbar word keeps its column and no golden's click coordinates move. test/snapshots/ttyhelp.snap pins it from a bare boot: click Help, get the list, shell still TTY at its prompt, then Ctrl-b + SPC ? for the keyboard route. All 58 goldens carry row 0, so all 58 moved. Verified mechanically that the only changes are the row-0 text and the row-0 style run (0-47 -> 0-52), plus: dump/restore record the topbar inside their .zon, and tagnav's `$`+Enter now executes `Help` rather than `Grep` because the bar's last word changed — still exactly what that step's comment claims it tests. THE DEPENDENCY FIX HAS A CEILING, NOW STATED. The module map is consulted from OUR goto handler, not from inside ZLS, so the analyser still cannot type the `vaxis` const: `gd` on `@import("vaxis")` opens the file, `gd` on `vaxis.init` finds nothing. That is now spelled out at the top of lsp_zls.zig and on moduleRoot rather than left implied, and `SPC l w` detects the case by name — if the left side of a failed field access is a known dependency it says so, instead of the generic "could not resolve". Lifting it means giving ZLS a real BuildConfig, either by letting it run the build runner (a subprocess, and with no cross-query cache that is once per keypress) or by synthesizing one into BuildFile.impl. Both are real work and neither is smuggled in. Also fixed while there: the field-access miss was only explained when ZLS returned null, but it returns an EMPTY SLICE when it typed the left side and found no such member. Both are "gd did nothing" from the outside; both are explained now.
Diffstat (limited to 'test/snapshots/leader.snap')
-rw-r--r--test/snapshots/leader.snap53
1 files changed, 30 insertions, 23 deletions
diff --git a/test/snapshots/leader.snap b/test/snapshots/leader.snap
index e06d5a3c..7cd0b98d 100644
--- a/test/snapshots/leader.snap
+++ b/test/snapshots/leader.snap
@@ -6,10 +6,6 @@
# pane with no file behind it, like +Search). The paths, the Help lines and
# the execute dispatch are all folded out of ONE enum at comptime — so
# executing the WORD `Help` runs the same builtin the leader does.
-#
-# The single-letter slots k/r/a/h/s/S/d/D belong to helix's LSP commands, so
-# pardes's own builtins live around them: Kill on `q`, Del in the window group
-# as `w c`, Dump/Restore in the file group, Tutor on `T`.
file cmds.txt Help
start 40 100 cmds.txt
wait 8000 Kill Newcol
@@ -19,10 +15,10 @@ stable 700 20000
key space
stable 400 5000
snap spc
-# ... and grows as the path is typed (`f` = the file group)
-key f
+# ... and grows as the path is typed (`h` = the docs group)
+key h
stable 400 5000
-snap spc-f
+snap spc-h
# Esc abandons the sequence: indicator gone, nothing ran, cursor untouched
key esc
settle 100
@@ -31,43 +27,43 @@ snap abandoned
# an UNMAPPED key abandons too, rather than waiting: a typo must not leave the
# next keystroke armed at a builtin that closes panes
key space
-key z
+key q
stable 400 5000
snap unmapped
# executing the WORD `Help` (middle-click) runs the builtin — the enum IS the
# lookup, so a name works anywhere text lives. Every builtin, with its keys.
press middle 9 3
release middle 9 3
-wait 10000 SPC T
+wait 10000 SPC h t
stable 700 15000
snap help-word
-# `SPC f ?`: only the `f` group, rewritten into the SAME +Help buffer
+# `SPC h ?`: only the `h` group, rewritten into the SAME +Help buffer
key space
-key f
+key h
key ?
-wait 10000 under SPC f
+wait 10000 under SPC h
stable 700 15000
snap help-group
-# `SPC T`: the Tutor builtin, zero arguments. It runs from the +Help pane,
+# `SPC h t`: the Tutor builtin, zero arguments. It runs from the +Help pane,
# but that is an output pane and not a document — so the tutor lands under
# cmds.txt, the real doc, with the listing left at the foot of the column.
key space
-key T
+key h
+key t
wait 10000 PARDES TUTOR
stable 700 15000
snap tutor
-# `SPC w c`: Del is pane-scoped — it closes the tutor, focus falls back. It
-# sits in the window group because closing a pane IS a window operation, and
-# because `d` now belongs to the diagnostics picker.
+# `SPC d`: Del is pane-scoped — it closes the tutor, focus falls back
key space
-key w
-key c
+key d
stable 700 15000
snap deleted
-# `SPC ?` at the root lists everything again
+# `SPC ?` at the root lists everything again. Waits on an EARLY row: the full
+# listing outgrew this pane when the language group landed (Restore, which this
+# used to watch for, is now row 21 of 33 and falls off the bottom).
key space
key ?
-wait 10000 SPC f r
+wait 10000 SPC c n
stable 700 15000
snap help-all
# `SPC t ?`: the toggle group, seven of them now that the image renderer
@@ -79,14 +75,25 @@ key ?
wait 10000 Petscii
stable 700 15000
snap help-toggles
-# `SPC w ?`: the window group — the four focus moves, the terminal hop, and
-# Del. They are the tail of the full listing above and fall off its bottom.
+# `SPC w ?`: the window group, whose five builtins are the tail of the full
+# listing above and fall off the bottom of this pane there
key space
key w
key ?
wait 10000 Toggleterm
stable 700 15000
snap help-window
+# `SPC l ?`: the LANGUAGE group — every LSP command lives here rather than on
+# the bare `<space>` letters helix uses, so `d` stays Del and `k` stays Kill.
+# Each one keeps helix's own letter INSIDE the group (hover k, rename r, code
+# action a, symbols s/S, diagnostics d/D, select-refs h), plus the two
+# introspection builtins that are ours: i and w.
+key space
+key l
+key ?
+wait 10000 WsDiagnostics
+stable 700 15000
+snap help-language
# Esc in the BODY of an output buffer IS Del: +Help has no file behind it and
# nothing worth keeping, so the key that elsewhere only drops a selection
# dismisses the whole pane and hands its height back to the pane above.