| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
| |
Plus docs/lsp-evaluation.md: the three backends measured head to head.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The base every language backend plugs into. Three parts:
ASYNC. The core had no request/response shape - every effect was
fire-and-forget or instantaneous. A language query is the first thing
that answers later, so: Effect .lsp -> shell worker -> Event .lsp_resp.
tty.zig uses io.concurrent + the vaxis queue, gui.zig a detached thread
+ the mutex queue it already had for ptys; web no-ops it. The worker
never touches the core (path/source/arg are snapshotted into an LspJob),
one query in flight identified by a monotonic id so a second press makes
the first answer stale, and no rows is a legal answer.
KEYMAP. Helix's, verified against its default.rs rather than recalled.
gd/gD/gy/gi/gr and ]d/[d had no conflicts. The SPC letters did, so
pardes's own builtins moved instead of helix's: Kill k->q, Del d->wc
(closing a pane is a window op, and c is helix's own close), Dump/Restore
s?->f?, Tutor ht->T. A three-exception muscle-memory map is not a map.
RESULTS ARE +SEARCH ROWS. path:LINE:COL text, absolute. That is what
look.zig resolves and n/N step, so one row from a goto jumps and several
open a buffer - helix's multi-result picker needed no picker code.
Backends supply exactly one function (lsp.query) plus a supports set and
a name; the base has none on purpose. zig build lspbench scores them on
the same corpus: feature matrix (trusting results, not the supports
flag - a claimed-but-empty kind is reported as a false claim), cold and
warm latency, peak RSS.
Two snapshot scripts moved. leader.snap encoded the old key paths.
chordcut.snap's last two steps clicked column 5, which lands on a FILE
pane, so 'key c-b' toggled nothing and the typed text was being read as
normal-mode keys - the golden recorded no TTY pane and no cat -v output
anywhere. Pointing them at an actual shell makes both steps assert what
their comments claim, and the tty paste chord is now covered for the
first time.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
selects but never edits
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
asked, never into a column of their own
placeDoc classified any file pane as a doc, so a +Search opened from a lone
shell took layoutInsertColumn(0) - a whole new leftmost column, shoving every
existing column sideways - and an open results list was then eligible as the
split parent for a real file, stacking documents under the list. An output
buffer has no file behind it and no Save; it is the result list belonging to
the pane that asked for it. Now it is that on both sides of the rule: it
splits below from_id whatever kind of pane that is (a source that died falls
back to stackDocLeft, the same last resort a full column bar uses), and it is
skipped when a real doc hunts for its split parent, so a file opened from a
search row joins the docs instead of the results.
Real docs are untouched: fsearch/rsearch/look-file/tutor/lookpanes all pass
unchanged. psearch is the proof - its results snap was two columns (the shell
pushed to x=70, its gutter run at 70-71) and is now one 140-wide column with
the +Search stacked below at the same x origin.
|
| |
|
|
| |
most-recently-focused, search only when all fail
|
| |
|
|
|
|
|
|
| |
Colors lifted from the user's own helix theme (~/.config/helix/themes/pardes.toml,
pinned against a real hx render through a pty). Theme gains box/box_dim so a
restrained theme can turn the accent down; the hardcoded gray.* overlay greys
were the dark theme's own fields spelled twice and are gone. The old default is
still one NextColor away.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The image tag spelled out `Petscii <C64|Term> Ascii` and actOnSelection
matched those words by hand before the builtin dispatch. They are three
real Builtins now (SPC t p/l/a), so the by-word matching is gone, the tag
is a plain `img <path> Del`, and with nothing live left in it the image
early-returns in curTail, enterTagEdit and the tag-click guard go too — an
image tag edits like every other pane's.
Colors and Crt leave the topbar for SPC t c / SPC t r: set-once display
switches should not spend width in a bar you read every frame. NextColor
stays, it is the one you cycle repeatedly. Both remain full builtins.
The snap scripts that clicked those words now press the leader instead, and
images.snap finally exercises the palette and ascii toggles for real: its
old clicks at x=57 landed on the neighbouring shell's tag, so that toggle
had never been covered. The test PPM grew to 512x512 with LCG noise so the
ASCII bitmaps actually win cells and dropping them visibly changes the art.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Left/Down/Up/Right run the existing focusDir (now taking the pane the
builtin ran on, so an executed name acts on ITS pane); the Ctrl-w prefix
routes through the same four builtins instead of calling focusDir itself.
Toggleterm hops between the most recently focused document and terminal
off focus_hist, the MRU the core already rebuilds each sync.
Ctrl-w stays: a tty-mode pane never sees SPC, so it is the only keyboard
way out of one. Its snapshot step now moves focus somewhere (c-w l), which
the old c-w h in that layout did not.
|
| |
|
|
| |
Save moves w -> f s to free the w group for window navigation.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
the next left click instead of stretching to it (explicit v/x selections keep click-extend), and in a tty-mode shell 1-3 now pastes into the pty like a terminal emulator — the click is forwarded first (SGR or X10, only when the app listens for mouse) so mouse-aware programs paste at the click point, then the register arrives bracketed (mode 2004) or with \n->\r when unbracketed; 1-2 stays inert there. chordcut.snap pins both (a cat -v probe shows the exact wire bytes); tutor updated.
|
| |
|
|
| |
(file:LINE works) opens it focused in the left column with a greeting terminal on the launch dir at right, a DIRECTORY arg chdirs so shells spawn there. New argv.snap; boot/restore.snap pin -n 1 to keep the classic boot.
|
| |
|
|
| |
the new pane under 2 body rows, splitParent swaps in a qualifying pane (same column first), else the tallest pane anywhere; applied to Alt-n, look-dir, placeDoc and ttyForDir. New splitparent.snap.
|
| |
|
|
| |
BOX_H (the tag row doubles as the re-enlarge handle; the gutter move box wins over the handle so a tag-only pane stays movable), a hidden body's pty/vt is never resized so re-enlarging restores it intact, and cursor/modal-selection paints never land on the tag row. New shrinktag.snap; tutor updated.
|
| |
|
|
| |
middle-drag pane has no selection of its own (kept left sel, else explicit v/x n/N), the active pane is checked first (it holds the most recently made selection), then slot order. New selarg.snap covers borrowing a kept left selection and a v selection from another pane; tutor updated.
|
| |
|
|
| |
looked word (and its cwd-join) is matched against loaded file/image pane paths first, honoring :NN recentering — so the fs-less web build can focus dump-loaded panes on look, and native dedup no longer needs the file on disk. New lookloaded.snap: look at a path after rm'ing it still focuses/recenters the loaded pane.
|
| |
|
|
| |
(both in one hold = Snarf/copy; the chorded left release is inert), plus 2-3 / 3-1 / 3-2 cancel an execute or look drag mid-gesture (the 2-1 argument chord already existed). chordcut.snap covers cut/copy/paste and both cancels; tutor documents the chords.
|
| |
|
|
| |
scrolled view even when the pane isn't active (the old gate only protected the active pane; tag edits use the remembered body mode). New ttyfollow.snap: background job streams into a scrolled-up normal-mode pane without moving it, tty mode follows again.
|
| |
|
|
| |
longer force-drops to normal (it only restores the mode a tag edit hijacked, remembered in pane.tag_mode), and the left-release cursor pin keeps the terminal's mode (files still click into normal). New ttyclick.snap covers tty body click, tty tag round trip, insert body click.
|
| | |
|
| |
|
|
| |
mode. Surface.cursor grew a bar flag: the core sets it from the active pane mode (insert -> bar; normal/tty -> block) for both the modal/file cursor and the vt-tracking terminal cursor, and unconditionally for the tag cursor. tty shell: DECSCUSR via vaxis setCursorShape (beam for insert, the terminal default otherwise). gui shell: the insert cursor draws the left-eighth-block glyph in cell colors instead of the reverse-video block (ponytail: it hides the char under it; a dedicated quad if that ever matters). Tag editing: enterTagEdit goes straight to insert, Esc (or anything that exits the tag) restores the body normal mode; Enter looks / Tab executes the word at the cursor from inside the tag (tagChordText kept); the whole normal-mode tag machinery — handleTagKey motions, v/x selection, d/c/y/p, tagEnterInsert/tagDelete/tagYank/tagPaste — deleted as unreachable (~120 lines; multi-word tag execution stays the mouse middle-drag). tag.snap rewritten: INS on click, type/backspace straight in, Esc exit with the text persisting, Enter-look opens the file. Tutor documents it. Cursor SHAPE is not capturable by the harness (position only) — verify by eye: bar in insert/tags, block elsewhere, both shells. 30/30.
|
| |
|
|
| |
scroll): pane.hscroll cuts content columns after the lineno gutter in bodyText (post edit-splice, so typed runs shift with the text), no scrollbar. Drivers: horizontal wheel (new wheel_left/right Mouse.Buttons, SGR 66/67 via vaxis on the tty, SDL wheel.x on the gui, ±4 cols, clamped at 0, right overscroll allowed) and keyboard movement — ensureCursorVisible grew the horizontal mirror of the scrolloff reconcile, so $ pulls the view right with 3 columns of margin and 0 reels it home; the wheel never moves the cursor. Shifted alongside: syntax recolor pass, modal cursor paint (hidden when off-view), vsel highlight, click->content-col mapping, cursorWordSel. Byte columns like the rest of the file-pane code. New hscroll.snap golden: wheel shift with fixed gutter, left clamp, $ margin follow, 0 home. 30/30.
|
| |
|
|
| |
next/prev whitespace-separated token that look.resolve can open (several per line: the greet ls row hops big.txt -> plain.txt -> sub), park the cursor at the token start, open NOTHING. Enter's existing normal-mode handler does the look on the selection (dir -> shell+ls there, file -> pane), so navigation continues with n/N+Return inside whatever opened. Wraps when nothing lies in the motion direction (first n out of tty mode starts at the prompt row and lands on the first token — lookStep pins the cursor first). vsel anchors the token end, cursor at its start (vselText is end-inclusive). File-pane search n/N untouched. ttylook.snap rewritten for the new semantics: token hops with selection styling, insert-mode n still types, Return-opens-dir, empty-dir no-op, cursor-word Enter opens a file. 29/29.
|
| |
|
|
| |
into the live session. dump.outPath resolves $PARDES_DUMP verbatim (the snapshot harness pins /tmp/pardes-dump.zon so dump/load/restore goldens stay deterministic), else $XDG_DATA_HOME|~/.local/share /pardes/pardes-YYYYMMDD-HHMMSS.zon (dir mkdir-ed; wall clock via libc clock_gettime — std.time.timestamp is gone in 0.16). After write_dump the shell reports the written path back (core.setLastDump) and the topbar grows "Restore <path>": middle-clicking Restore reloads the last dump, and "Restore <path>" executed anywhere takes the path as its first argument (onSelect prefix match). Core stays sans-IO: the builtin stashes restore_req; each shell consumes takeRestore() after drainEffects and swaps in initFromDump at the current screen size (pre-sized: dump panes never greet), tearing down the live ptys (tty: cancel reader + close + gen bump; gui: SIGKILL, the gen-guarded eof closes the old fds). Web ignores it. New restore.snap golden: KEEPME survives the restore, GONESOON echoed after Dump does not, the topbar word appears then resets. 29/29.
|
| |
|
|
| |
gives the classic two-column boot), -n <count> CLI flag. The 26 legacy snap scripts pin -n 3 on their start line so their coordinates and goldens stay valid; boot.snap tests the new default (golden regenerated: one full-width pane). 28/28 green.
|
| |\ \ \ \ \ \ \ \
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
three merge-state fixes born of branch interactions.
Branch work merged: tty exit cleanup (krluslzz), drag-select effect-queue crash (zopqvlll), single-pane layout rule (tutmotnl), tty input coalescing + -Dtracy (olnvomwz), / file search (syqzvmkl) + generalized n/N look motion (nmzypsto), ghostty middle-click diagnosis (sqonpmsz), NOR/INS/TTY mode indicators (opmrortk), cursor-row gutter highlight (nymrwpwq), look path:NN centering (oktvtuss), scrolloff (wlqqyvvo), posix portability (pzwluyuw).
Merge-state fixes: (1) splitBelow caps keep at body-(BOX_H+3) so a content-full source still leaves the new pane a tag + a few body rows — Alt-n from a full shell was born 0 rows tall (caught by ttylook: OVER marker had no rows to render in). (2) spawn-effect pane-id reuse crash (user-reported panic at drainEffects assert): no close effect exists, so a deleted pane pty lingers in its slot until a respawn lands on it — both shells now reap the stale pty at spawn (tty: cancel reader + close; gui: SIGKILL, reader delivers the old fd through the eof event) and per-slot generations drop the dead shell late output/eof, which otherwise nuked the NEW pty on the reused id. New respawn.snap golden; fails on the pre-fix assert. (3) dedup re-look now lands the modal cursor on the target line (cur_row/cur_col/cur_pinned) — scrolloff cursor-anchored reconcile otherwise yanked the recentered view back to the stale cursor (caught auditing look-center: center-dedup stayed at 97-102 instead of 146-154); this is also the requested focus-moves-cursor behavior. look-center dedup/clamp clicks re-aimed for the merged layout geometry (typed row moved from 18 to 15).
Goldens reconciled by regenerating from the merged binary and auditing every diff against its origin branch; deltas are exactly: indicator text/width shift, layout-split pane sizing, cursor-row gutter styling, centering shifts, and the pane-edge hover dash now coinciding with new pane boundaries. Suite: 28/28 (27 + respawn).
|
| | |_|_|_|_|_|_|/
|/| | | | | | |
| | | | | | | |
| | | | | | | | |
(vim scrolloff). One reconcile in Pane.ensureCursorVisible — every keyboard path (normal-mode motions, insert entry/edits, delete/yank/paste/undo/redo) already funnels through it; mouse click/wheel untouched. Clamps: line 0 at top, EOF-at-bottom-row for files (terminals let the vt clamp at the live bottom), margin shrinks on panes shorter than 2*off+1. New scrolloff.snap golden proves j-walk scroll at the margin, gg/top-row reachability, k-walk margin, G bottom clamp. 19/19 snapshots green; no existing goldens changed.
|
| | |_|_|_|_|_|/
|/| | | | | |
| | | | | | |
| | | | | | | |
body/2, clamped at 0): fresh opens lay out first (computeGeom after placeDoc) to center with the real body height; dedup re-looks recenter the existing pane. look-file golden shifts accordingly; new look-center snap proves fresh-open centering, dedup recentering, and the top clamp.
|
| | |_|_|_|_|/
|/| | | | |
| | | | | |
| | | | | | |
tag style (tag_fg/tag_bg), resolved at render time from the theme like the rest of the chrome. Same row math as the cursor pass (pinned cur_row or emulator cursor + scroll), gated on active && !tag_edit so only the focused file pane shows it. New cursorline snap script + golden proves it follows j-movement; look-file/syntax style goldens regenerated (cursor-row gutter cells only). 19/19 snap green.
|
| | |_|_|_|/
|/| | | |
| | | | |
| | | | | |
+ dump-load tty detection (startsWith "TTY "), tutor.txt docs, exec/fileedit snap tag-click cols +1 for the wider prefix, all 18 goldens regenerated (indicator text + 1-col tag shift only)
|
| | | | | |
| | | | |
| | | | |
| | | | | |
own output rows — paneCursorLines, prompt/echo rows already blanked by the OSC 133 marks — for the next/prev row whose leading file-ish word resolves through look.resolve (realpath-only, side-effect-free; only the chosen row gets the real look), msel-select it, scroll it into view, and look it via actOnSelection. The modal cursor is the position (no new Pane state), so the walk resumes wherever j/k left it; focus returns to the terminal after the look so n keeps stepping; no wrap; no hit = no-op. Insert mode still splices, tty mode still forwards to the pty. The file-pane search stepper stays separate (different row predicate: the searched file's path prefix vs general resolvability). New snap script ttylook.snap + golden; all 19 baseline goldens untouched and green (20/20).
|
| | |_|_|/
|/| | |
| | | |
| | | | |
existing modal one-line editor — persistent, no popup); Enter runs grep -nH '<pat>' '<path>' in a shell in the file's dir via the existing exec path (ttyForDir + write effects), so results are ordinary persistent terminal text. n/N walk the result rows of that pane (paneCursorLines already blanks prompt/echo rows via the OSC 133 semantic marks), select the row with the modal line selection, and hand path:NNN: to the existing look (actOnSelection right) which scrolls the file pane there. Esc cancels and restores the tag. State: four Pane fields (search_edit/search_at/search_pane/search_row) — no results mirror, no highlight engine. New snap script fsearch.snap + golden; all 18 frozen goldens stay green (19/19).
|
| | |_|/
|/| |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The tty shell rendered (core.render + full vaxis repaint + tree-sitter
re-highlight of the visible window) after EVERY event, so a wheel flick over a
highlighted file was 150 re-parses and 150 terminal repaints; the gui shell
drains the SDL queue before drawing and never had the issue. Now the tty loop
applies every queued input event, then renders once (batch cap 64; pty output
keeps a frame per chunk so progress paints and transient-state waits behave
exactly as before). Measured with tracy on a 2400-line .zig scroll script:
150 highlightFileRange calls at 1.85ms mean -> 4; render pipeline total
730ms -> 64ms; 364 frames -> 39. Snap suite 18/18.
Tracy: -Dtracy=<path-to-tracy-checkout> compiles TracyClient.cpp into the
binary and turns src/tracy.zig zones live (default off, all no-ops). Sampling,
callstacks, system tracing and the crash handler are disabled: tracy's symbol
worker SIGSEGVs on this binary's debug info and its crash handler then parks
every thread before the first frame. Capture: tracy-capture -o t.tracy; export:
tracy-csvexport t.tracy.
|
| | |/
|/|
| |
| | |
whole column. Buggy paths fixed: Alt-n inserted a weight-1 shell (whole column reflowed) — now splitBelow the active pane; stackDocLeft (file/image/tutor open with no doc yet) gave the doc a fair share (every pane shrank) — now it halves only the old top pane's slot; ttyForDir (execute from a file pane) appended a weight-1 shell to the rightmost column — now splitBelow its bottom pane; Alt-c moved a pane out without absorbVWeight (all old siblings grew) — now the sibling above absorbs first. Underneath: splitBelow/absorbVWeight/stackDocLeft snap the whole column's weights to on-screen row counts, because computeGeom's per-pane round(avail*w/vsum) let fractional weights jiggle bystanders by a row; evictLonePristineTty recomputes geometry first (a just-stacked doc has no rect). New snap tests layout-open + layout-close cover Alt-n, doc stacking, ttyForDir, Alt-c, tag Del, pty EOF, and column-width handoff. Six goldens regenerated (fileedit, images, look-file, syntax, tutor, windowops): they had frozen the fair-share/append reflow this change removes; every diff is only the doc/split pane sizing, with untouched panes' boundaries restored bit-identical (e.g. bottom pane tag back at its boot row 17 instead of pushed to 22).
|
| |/
|
|
| |
update emitted a big selection exec (emitWrite 64-byte chunks + padOutputBelowEdits CRs) and the emit assert panicked. Effects queue is now a growable ArrayList FIFO (payloads stay inline values); guard the two other Buf(256) asserts reachable from look (spawn cwd >256 -> error.PathTooLong in newShell, >256-char url skipped). New snap exec-bigdrag: giant middle-drag exec on a 60x200 grid, panicked before, alive-marker golden after.
|
|
|
test/ (snapshot parity harness + 18 frozen goldens). One sans-IO core, vaxis tty + SDL3 GPU native + wasm web shells, 18/18 parity with the purged prototype, 7.6k lines vs 12.1k. Fix: gui shell pre-sized the core at init so the greet-releasing resize never fired (blank panes until first interaction); live sessions now init at defaults and get the real grid as a resize event (the shell contract, documented on Options).
|