| Commit message (Collapse) | Author | Age |
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An external update is pushed onto the undo stack exactly like an edit the user
typed, so unsaved work is one `u` away and pardes never has to merge anything.
That is the design, not an implementation detail: the whole feature is
pushUndo() then setContent().
One inotify instance in the tty shell, blocking in readVec through std.Io on a
concurrent task started beside the pty readers — after loop.start(), so the
forkpty ordering is untouched. It watches the containing DIRECTORY, because an
editor rewrites by rename-over and a watch on the file would follow the dead
inode, and it listens for CLOSE_WRITE rather than MODIFY, which is one event per
finished writer and most of the debounce for free.
Our own Save does not reach the undo stack: each watch keeps a hash of the
bytes last seen on disk and save_file restamps it. A hash rather than mtime and
size because the reload has to read the file anyway.
The core stays sans-IO — one watch effect out, one file_changed event in, and a
shell that cannot watch simply never sends the event, which is what the gui and
the web platform do. Linux only; fanotify is what the build system uses and is
rejected in a comment: it exists for thousands of directories across mounts,
and sixteen panes of inotify is a third of the code with no kernel floor.
New golden filewatch: edit without saving, overwrite from a shell in another
column, watch it reload, undo, get the unsaved edit back. None moved.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
queryTerminal(2ms) blocks on a futex until DA1 comes back, and the number has
to beat one terminal round trip: local answers in microseconds, ssh localhost
under a millisecond, any real link never. Measured against sshd with the
replies delayed to model the wire, 2ms already loses at 5ms RTT.
Losing it is worse than never probing, because vaxis splits detect from enable
and only detect respects the deadline. The flag flips the moment the futex
times out, so the two replies gated on it — explicit width and scaled text,
both spelled as a cursor-position report — stop being read as probe replies and
arrive at the app as shift-F3 and alt-F3 keypresses, while the ungated ones
keep mutating caps from the reader thread long after enable already declined to
switch those modes on. Over ssh the terminal sat in its default modes while
caps claimed otherwise: kitty keyboard was never actually pushed, ever.
So send the probes and resolve them on the loop. DA1 is last and terminals
answer in order, so when the reader flips the flag every earlier reply is
applied — no window to miss at any latency. Verified over real ssh at 5 through
500ms RTT: 7/7 caps and kitty keyboard actually enabled at every one, where
before it was 5/7 and never. Startup is 2ms faster, no golden moves (nothing
answers in the harness, and with no caps enable writes no bytes).
Honest scope: I could not reproduce the reported stale characters, only the
handshake bug behind them. The width half of the theory is inert — vaxis's
Cell.width defaults to 1 and pardes writes one codepoint per cell with an
explicit spacer, so gwidth, the only consumer of caps.unicode, is never called.
That is written down so nobody re-derives it. If the dirty screen survives,
the next suspect is vaxis's own carry-over for an escape sequence split across
a read boundary (Loop.zig:174-190, wrong length and an off-by-one): four wheel
events sent whole scroll four notches, the same four split at a `;` with a
60ms gap scroll zero. Network framing is exactly what makes those gaps. It is
an input bug in a vendored dep and wants its own change.
|
|
|
their own files
The core now lies FLAT at src/ and every subdirectory is one backend, so a
file being in no directory at all is what says it is core. Pane-kind bodies
leave pardes.zig for term_pane.zig / file_pane.zig / output_pane.zig, leaving
it the layout, the event/effect machine and the generic render loop.
Builtins are one struct each in builtins.zig, and the enum is folded out of
the file's own declaration list at comptime — a zig file IS a struct, so the
list of builtins and the builtins themselves are the same text. Adding one is
writing a struct. Key paths deliberately stay one table for the config pass.
Pure refactor: no golden moved.
|