| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
| |
Consolidate pane, layout, memory and host code. Serve 9P by default over Unix sockets, with runtime mounts and optional TCP/QUIC transports. Remove FUSE and obsolete proof-of-concept examples.
Fix highlighting and terminal-history performance, expand differential and stress-test infrastructure, sort navigation results while preserving the next occurrence, add syntax-colored Braille minimaps, remove SPC-k, and document 9P interaction as a repository skill.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
effects that compile
Three things this shell had its own copy of, and in each case the fix is that
it stops having one.
**The tagline band.** A pane tag draws at `gui_tagline_font_percent` of the
body face and the band it sits on shrinks with it, while the grid row stays
body-sized — so something has to decide where the shorter band sits in the
taller row. This shell decided by centring, always, which is precisely the case
`config.gui_topbar_pane_border_px` exists to prevent: the topbar's unused
half-band meets the first pane tag's unused half-band and the window background
shows through the seam. The strip is as wide as the bands are short — on a
20-pixel cell, 4 physical pixels at the default 82%, 10 at 50%, 14 at 30% — so
it grew as the tagline face shrank and read as "the tagline is wrong on the mac"
rather than as one missing rule. The rule is `pardes.taglineBandOffset` in the
core now and both pixel hosts call it: row zero bottom-aligned, the first
pane-tag row top-aligned, the two joined by `gui_topbar_pane_border_px` in the
theme's scrollbar-track colour, every row between centred, and a `Tagbottom`
band on the final row flush with the window edge — with the sub-cell strip
beneath it painted in that band's own colour, because the core grid holds only
whole cells and a window is any height it likes. `pardes_tagline_band_offset`,
`pardes_topbar_pane_border_px` and `pardes_topbar_pane_border_rgb` carry it over
the C ABI as PHYSICAL pixels: the host multiplies its points by the backing
scale going in and divides coming out, which is the snapping `Metrics` already
does for the cell, and is what keeps a one-pixel rule one pixel instead of a
two-pixel smear.
**The watch.** `file_watch.zig` was one mark/reconcile transaction over
`inotify`, so the tty shell, the SDL window and the detached daemon all watched
nothing off Linux: an edit made outside pardes never reached the pane, and a PDF
replaced on disk kept rendering the old inode. It is the same transaction over
two kernels now — `init`, `wait`, `stop`, `drain`, `markDir` and `unmarkDir` are
still the whole of it, and the hosts wait on a kqueue and poll it exactly as
they did the old descriptor. A macOS mark is TWO filters, because a kqueue
directory filter reports its entries changing and never a write to a file
already inside it: the parent mark follows rename-over saves, `markFile` catches
in-place writes, and `remarkFile` re-arms the file filter once a rename has moved
the inode. That is the same pair the AppKit host's DispatchSources already used
for the same reason. Directory marks are deduplicated here by device and inode,
because each `EVFILT_VNODE` filter needs a descriptor of its own and inotify did
that deduplication itself; `stop` and `drain` wake through the one `EVFILT_USER`
filter, since a kqueue cannot simply be read the way an inotify descriptor can.
**The effects.** The three `crt.ci.metal` entry points are
`extern "C" [[stitchable]]`. `CIKernel.kernels(withMetalString:)` compiles that
source at runtime, looks for stitchable functions, and rejects the WHOLE source
with "cannot find a valid stitchable Metal function in the source" when it finds
none — so `ScenePostprocessor.init?` returned nil and every scene effect and
panel transition silently degraded to the plain CoreText draw. The
`effect_sources.zig` test pins the exact spelling of all three, and
`draw-effect` in the e2e suite catches the degradation rather than the spelling.
Beside them, the offscreen harness owes the core a PRESENTATION. Its window is
borderless and never ordered front, so AppKit runs no display cycle and
`pardes_frame_presented` — whose only caller is `draw(_:)` — never fired. The
core holds pointer gestures inert while a layout mutation has not reached a
backend, which for an unpresenting harness is the rest of the script: the first
pane a script opened silently killed every later click, drag and Look. So
`readFrame` presents what it just rendered, into a bitmap nobody reads.
`PARDES_CHROME` also looks under `/Applications`, where a browser's executable
lives inside an application bundle and never on `PATH`. The macOS goldens are
regenerated; docs/macos.md, config.md, detached.md, web.md and the design PDF
follow.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Esc stops recentring
## A terminal row's ANSI colours survive being edited
The loudest colour bug this editor had: one keystroke anywhere in a coloured shell row turned EVERY
column of it grey. `EditAnchors` anchored a buffer line only when it was BYTE-IDENTICAL to the shell
row it stood over, so a single differing byte dropped the whole row's colour projection. Worst shape
is invisible: append past the pane's right edge, where the text is clipped, and the row looks the
same and only its colour goes.
Anchoring is byte-level now. An edit leaves the row's own bytes at both ends, and being the same
bytes they keep the same colours; only what was typed has no cell under it, so only that takes none.
Live, on real `fastfetch`: a 32-column blue run split into 6 + 26 around one typed character.
Three defects underneath it, all found by machinery rather than by reading:
* A JOIN removes a buffer line while the buffer's covered span grows, so `lines == covered` and both
aligned guesses — Nth line over the Nth covered row, and the same counted from the bottom —
resolved to the SAME wrong row. Every untouched row below a join went plain. Anchoring is now a
streaming monotone matching: one shell-row cursor that only ever moves forward, advanced once per
buffer line, linear in the buffer where the version before it was quadratic.
* An EMPTY line is not evidence. Splitting a row makes one, it equals every blank row in the span,
and left free to look ahead it claimed the blank row below the last output and took every coloured
row in between out of reach of the lines that owned them.
* Reflow under a scrolled viewport. `PageList.getTopLeft(.viewport)` returns the viewport pin
verbatim, x and all, while `PageList.pin` forces x to 0 — so after a reflow remapped a tracked pin
into the middle of a row, the text pass dumped row 0 from that column while the colour pass paired
the fragment with the row's FIRST cells. Row 0 wore its left half's colours until the pane snapped
back to live output. `bodyText` dumps from column zero now, which is also what ghostty's own
renderer draws.
Also here: DECSCNM (reverse video) was silently dropped whenever `tty_filter` was off, because the
raw path resolved a `.none` colour by role and never consulted the mode.
The test that found the first two is the one worth keeping: random editing against an ABSOLUTE
oracle — every row's own text names the colour it must have — because the differential oracle it
replaced was blind by construction. It skipped the edited row, which is the row the user is
complaining about.
## Esc returns to a pane without moving its view
Esc in body normal mode runs `Last`, "the pane you were in before this one", and that went through
`focusPaneLine`, which recentred a file on the target line unconditionally. So returning to a buffer
repainted the whole screen to show a line that was already on it.
`focusPaneLine` takes a landing now: `.center` for the three callers going somewhere you have not
been (a look target, a path a pane already holds, `@pN:LINE:COL`), `.keep` for Esc. `.keep` leaves
the view alone and lets `ensureCursorVisible` — which already existed and already scrolls by the
minimum into the `scroll_off` band — be the only thing that may move anything.
Not `line = 0`, which `focusPaneLine` already understands as "focus and touch nothing": a background
pane's view can move while you are away, because the wheel scrolls the pane under the POINTER and a
resize reveals no cursor, so the recorded cursor plus a minimal nudge is what actually gets you back.
Ctrl-o and Ctrl-i keep centring, and the asymmetry is structural rather than arbitrary: `Last` only
ever CROSSES panes, so the pane it lands on already holds the view you left it with, while `jumpBy`
can land in the SAME pane, where a long in-file jump would arrive on the very top or bottom row with
`scroll_off` lines of context on one side. Helix splits the same pair the same way — its jumplist
centres, its buffer switch does not.
One deliberate consequence: under `.keep` a PDF's page is not restored AT ALL, because a page reveal
IS that pane's view and a reveal of the page you are already on still snaps `document_scroll_y` to
that page's start, discarding where you had read to. When something moved the pane while you were
away — the wheel again — Esc leaves it where the wheel left it, and Ctrl-o is how you reach the
recorded page.
## host_io.zig: the machine-local half of a host, once
`host.zig` is the seam. The part of the answer that is identical on every host with an operating
system under it — fork a pane's shell, put bytes on a disk — was written FOUR times: in tty.zig,
gui.zig, macos.zig and detached/server.zig. What those copies had in common says what they were for:
all four were missing FD_CLOEXEC on the pty master, so in every shell pardes has shipped, a program
in one pane could read another pane's terminal.
One copy now, and the wire got smaller for it: `ServerMsg.spawn` is gone. A frontend never asked the
server to fork anything — the server has an operating system under it and forks through `host_io`
like every other host — and `decodeClient` lost the scratch buffer that message needed.
|
| |
|
|
| |
optional methods
|
| |
|
|
| |
backends agree
|
| |
|
|
| |
docs
|
| |
|
|
| |
+ snapshot refresh
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The documentation had gone stale in the ordinary way -- claims that were true
when they were written and that nothing since had been obliged to re-read.
Some of them were load-bearing.
THE TUTOR. It still said there is no multi-cursor, that NextColor cycles three
themes, and that its practice blocks "are also run as unit tests (generated
from this file by tutor_gen)" -- a tool that appears nowhere in the tree, and
nothing anywhere parses a `# keys:` block. Left alone, that claim is what
makes the next wrong block survive.
Three of those blocks WERE wrong, and all three for one reason: since the
helix motion model landed, w/e/f/t SELECT the range they cross, so `i` after
one inserts at the SELECTION'S START. `w i Z esc` on "foo bar" gives
"Zfoo bar", not the "foo Zbar" the file promised. They were written against a
vim reading of the same keys. Every block in the file has now been run through
`zig build hxdiff` against the real core and matches byte for byte, and the
trap itself is written down in 3.3 rather than left to be rediscovered.
The tutor gains a PART 4 for everything added since it was written -- PDF
panes, the in-process ZLS backend, themes and fonts, the startup file -- and
PART 3 gains counts (and which keys ignore one), f/F/t/T, the whole g table
(bare `G` is a no-op; `ge` is the START of the last line), multiple cursors
and the s/S regex pair, `m`, `]`/`[`, `|`, insert mode, and all fifty leader
paths.
THE REST. design.typ's line table claimed 7,626 lines against a real 38,048,
and its rows did not sum to its own total; its Event/Effect boundary contract
-- the part a shell author writes against -- named four variants that do not
exist and omitted fourteen that do. lsp.md's probe count. config.md's
theme-name rules, which as written could not reach a zed theme at all.
helix-keys.md's Skipped section, holding five families that have since landed.
macos.md's menu bar, undocumented, along with sixteen other claims. web.md on
what the browser build can actually do.
SOURCE COMMENTS that had rotted alongside them: `tag_normal` is a space, not
the `•` its own comment describes; Wrap is ON by default, not off; a FontSel
row is SELECTED by n and RUN by Tab, not run by n; the SPC paths in lsp.zig
lost their `l` group prefix when the language group moved; and the
differential suites are 481 and 561 cases, not 360 and 440.
TWO THINGS FOUND BY DOCUMENTING THEM, both left standing and written down
rather than papered over. Typing `[^\n]` at an s/S prompt panics: the live
preview compiles every prefix, and `[^\` indexes an empty slice in mvzr's
parseCharSet. Both the tutor and a waiver recommended that pattern as the
workaround for `.` matching a newline; they now say what it costs and what
would make it sayable. And `Exec` is a builtin, so an `Exec` line in the
startup config types that command into a shell before the first frame -- the
tutor said nothing in that file is ever sent to one.
Nine adversarial reviews over two rounds, each with the hxdiff harness to
execute what it doubted. The second round exists because the first round's
fixes needed checking too, and it caught three regressions of my own -- one of
them a probe count I had "corrected" away from the truth.
Verified: unit-test, snap 87/87, hxdiff 481/0, hxparity 561/0, mupdf-check.
docs/design.pdf regenerated. The tutor's first seventeen lines are byte-
identical, which is what tutor.golden pins.
|
| |
|