| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Every keystroke in a shell pane rebuilt the motion surface from scratch:
shellRows dumped ghostty's WHOLE history+active grid, split it, blanked the
prompt rows and handed back slices into the scratch arena, which the next
update threw away. A pane sitting on a multi-megabyte agent transcript paid an
O(scrollback) dump per press of `j`, and paid it once or twice per key, since
flatSurface then rebuilt the same rows joined by '\n' beside it.
The dump is now memoized against the pane it was built for (term_pane.RowsCache
on Pardes.shell_rows), gpa-owned rather than scratch-arena because the whole
point is to outlive the update that built it. One entry, not a table: the
surface is built for the pane the cursor is in, and a second pane asking would
only double a multi-megabyte buffer for a slot it is about to lose again. A
pane that is not the live one is answered from the arena as before.
The lifetime rule is the part that would have rotted silently, so it is one
rule and it is written down: `rows` is handed out to callers, so everything
that notices the entry has gone bad — output arrived, the grid reflowed, the
pane died, another pane wants the slot — only marks it `stale`, and the
buffers are freed in exactly two places, `sweep` at the TOP of an update
before any handler can be holding them, and `reset` when the editor goes away.
Nothing frees mid-update. dropPane clears the pointer immediately though: a
freed pane's address comes back from the allocator as a different pane, and an
entry still naming it would answer for the wrong grid.
Two things fall out of having the join already:
- flatSurface returns the memo's `text` verbatim when the lines it was handed
are the cached rows untouched, instead of rebuilding the join.
- paneCursorLines returns `rows` directly when there is no edit buffer, where
it used to copy the array one slice at a time to produce exactly what it was
given.
One bug on the way past, in the same function: an EMPTY edit buffer writes one
line but modal.lineCount("") is 0, so `ls` was sized one short of what the
loop writes — the same floor the paste site needs. Killing a whole line
(`A<C-u>`, `d%`) on a buffer covering the last row made that a length of zero.
And test/perf.zig grows the axis that would have caught this: a terminal
scoreboard beside the file one, three scrollback fixtures (64 KiB, 1 MiB,
8 MiB — half the ceiling) against render / output / resize-rows / resize-cols /
key-down / edit-char, sharing the existing text and JSON reports and the
--base comparison. resize-cols and resize-rows are both there because a COLUMN
change reflows every page in the list and a row change does not.
Measured on that table: key-down is 142 / 630 / 636 us across the three
fixtures — flat from 1 MiB to 8 MiB, which is the dump being gone, and render
flat at ~110 us throughout. What remains of key-down's step at 1 MiB is the
linear scan indexOf refuses to index for a terminal; that is now a ponytail
waiver naming its own price (615 us against 140 us) and the threading through
paneOff/panePos/paneLineStart it would cost, to be done the day 0.6 ms shows
up next to something anybody can feel.
|
| |\
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
theming, and mupdf -Djpx
Three commits off 38e9919 (macos-app@upstream) merged into main's ghostty bump.
No textual conflicts, and two things the merge needed:
- nested.zig asked libc for fstatat. Darwin has it; on linux std.c declares it
`void` (glibc hides it behind a versioned symbol std cannot name), so the tty
build stopped at 'type void not a function'. statNoFollow keeps fstatat on
darwin and asks statx on linux for the same three fields, which is what this
file did before the branch generalized it to both platforms.
- .DS_Store rode along with a797a1a. Deleted, and .gitignore now says so.
linux: snap 86/86, unit-test, image-harness and mupdf-check green. nested.zig
also type-checks for aarch64-macos.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The AppKit shell now draws what the core renders, follows the theme without a
relaunch, and builds into something you can hand to someone.
- Pixel attachments. Surface.images was dropped on the floor here, so a PDF
pane showed nothing at all: native_images is now set, pardes_image_s carries
the geometry the core already clipped, and PardesView keeps one CGImage per
(serial, page, revision) so scrolling costs a draw and not a decode. Image
panes get real pixels instead of the petscii fallback.
- Themes take hold live. pardes_tick never advanced the chrome animation, so
every tagline kept the previous theme's colours until the next launch and
the 16 ms re-pump spun for the rest of the session. pardes_theme_bg retires
the hand-agreed #121212 and drives the window background and the titlebar
appearance; a theme with no background of its own now gets a transparent
window over an NSVisualEffectView.
- The cell snaps to whole DEVICE pixels rather than whole points. Monaco
advances 8.4014pt at 14, so ceiling to 9 spaced every column 7.1% wider than
the face was drawn for.
- The dial is one notch per 10 degrees instead of 20, and a release keeps
turning in proportion to how hard it was thrown -- ramping up from zero at
the floor, so a slow twist coasts not a little but not at all.
- A file dropped on the grid is a click plus Look, so it opens beside the pane
it was dropped on. No drop concept was added to the core.
- The titlebar follows the focused pane: proxy icon, filename, and the dirty
dot. File.saved_revision is the watermark that last one needed.
- Config (SPC f c) prints the resolved startup config path.
- build.zig assembles, signs and packages the bundle itself; build-app.sh is
gone. -Dmacos-identity= takes a Developer ID, macos-dmg makes the image, and
the icon is Glenda.
|
| | | |
|
| |/
|
|
|
|
|
| |
- build.zig.zon: bump ghostty ba38b493 -> 82e53e3f (translate-c backport, fixes 404 on cold cache), update hash
- src/pardes.zig: adapt Terminal.init/resize to new std.Io signatures; fix display-column conversion for tabs and clicks past EOL (fileRawDisplayCol/fileRawAtDisplay)
- test/e2e_harness.zig: adapt to new ghostty_vt signatures
- snap suite 86/86 green
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Esc ran Toggleterm, which hopped between the newest DOC and the newest
TERMINAL. That distinction never earned its keep. It made Esc unpredictable —
which of three panes you landed on depended on their kinds, not on where you
had been — and it could not alternate between two files at all, which is the
case you hit most. Editing two files, Esc did nothing.
The replacement already existed. Last (SPC j j) is "the pane you were in
before this one, whichever it was": it walks the jump stack for the newest
entry naming a different pane and restores its line and column. So Esc, and
Shift-Esc in tty, now run Last, and Toggleterm is deleted rather than renamed
— a third implementation of "go to the other pane" was the thing to avoid.
SPC w t goes with it; the w group is the four directional moves, and the jump
group already had SPC j j.
Held down, Esc alternates. Two files, a file and its shell, a file and a
+Search — all the same, because Last has no notion of kind to get wrong.
This depends on the swap in the same series: Last reads the stack backwards,
and until hopping stopped appending, the pane you came from could fall off it.
windownav.snap needed only its keys and prose changed — its golden did not
move at all, which is the useful evidence here: for the one scenario the old
builtin handled well, Last produces an identical focus sequence.
Coverage for what it did not handle is new: a unit test opens a second FILE by
looking its name and asserts Esc alternates between two panes of the SAME
kind, which is the case that used to be a no-op.
Docs follow: tutor.txt, docs/helix-keys.md, docs/design.typ, and the builtin
index goldens, which are now one row shorter.
75/75 snapshots, both unit suites, and the macOS ABI build all pass.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
search/range look steps, goldens updated
|
| |
|
|
|
|
|
|
|
|
| |
config.tag_normal became a space when the mode moved into the layout box,
and 66 goldens still spelled the old bullet — the whole suite was red on
one character. Regenerated serially, and every file's diff is that
character and nothing else: replacing the bullets in the OLD goldens with
spaces is byte-identical to the new ones, so nothing else moved under
cover of the churn. The one bullet left in tutor.golden is the tutor's own
sentence about the badge, which the app still draws.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
file:LINE:COL-ENDLINE:ENDCOL, with the two short forms people actually type
reading naturally: file:412:9-21 on one line, file:412-418 whole ones. Ends are
inclusive. A path feature, not a search feature — a ranged path typed in a tag
or middle-clicked out of a shell's output selects just the same; search is only
its first consumer.
The dash is the fussy part. `-` was already a file char, so a ranged word
survives click expansion whole, but a range needs a number on BOTH sides or
my-file:10, build-2 and 2026-07-30 would stop being paths. Table-driven test in
look.zig for exactly that.
Selecting goes through the cellRange/setPaneRange pair the multi-cursor work
left, and hxOff clamps both ends, so a stale range selects what still exists
rather than crashing or reaching past EOF — pinned with an 8:6-400:9 range in a
nine-line file.
Producers: / search, Grep, and five LSP sites through a new spanRow — goto,
references, rename tokens and both symbol lists were throwing away real
protocol ranges at path:line:col. Left alone deliberately: Find rows are bare
paths with nothing to span, a jump is a spot not a span, and the diagnostic and
format paths only ever have a point, where half a range would be worse than
none.
One knock-on worth knowing: n now leaves an EXPLICIT selection, so a topbar
execute chords it. grep.snap's no-match step was silently becoming
`Grep TARGET`; it runs from the leader path now, which never chords, and the
dedicated chord steps stayed where they were.
|