| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
| |
Save of a pane's own file logged `save <serial> <name>`, and so did a
scratch's `Save path` (the pane takes that name). A `Save path` that
writes a copy of a file pane, or a terminal's scrollback, elsewhere
logged nothing, so a follower could not tell the file was written. It
now logs `save <serial> <path>` with the path written, once the host has
written it (events.noteLogAs). fs.md's log table says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
not permitted, EPERM, not an EIO
cloud9's engine passes a wstat that changes a name to the backend, and
the tree's setattr ignored the name: the rename answered as done, the
name did not change, and a mount then gave `mv` EIO. The tree names its
own files, so a setattr with a name is now refused, "rename not
permitted", which 9ns reads as EPERM. A pane's buffer is still renamed
through its name file.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
only fail
`name ~`, `name /` or `name foo/` renamed the pane to a directory, and
only its Save failed later. A name ending in `/`, the root, or one naming
a directory that is there is now refused at once, with words a mount
reads as EISDIR (`name: <path> is a directory, not a file`). The ctl word
name and a forwarded `pardes ~` go through the same check. fs.md says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
shared, rather than stacking one per word
Each word looked for in a terminal (clicked, or written to look), where
no file of that name was, opened another +Search in the same directory,
one per word, until the column filled. Such a search now refills the
directory's +Search, as the file searches and the +Lsp answers already
share theirs. A `/` search keeps a +Search per pattern, which n and N
walk across (psearch.snap), so the sharing is marked on the word look
alone (Pardes.word_look).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
| |
spends no column serial
A pane/new, look or exec refused ENOSPC made its pane before placing it.
The refusal closed the pane unannounced, but its serial was gone, so the
next pane skipped one. When sync removes a refused pane that holds the
newest serial, it now puts the counter back.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
a refused one stand
A `>` to a tag that a client sends in several writes is checked a write
at a time. When a later one is refused, the earlier accepted ones stay in
the tag. Buffering the whole open to apply it or none would cost more
than it saves, so fs.md now says what happens: each write stands on its
own, and only the refused one changes nothing. A test covers a
truncation, an accepted write, then a refused one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
address form is, not clamped
`#5,#2` and `#2,#99` were refused (addresses out of order, address out of
range), but the pair form `5 2` became 5..5 and `2 99` became 2..end,
silently a different range from the one asked for. A pair is now checked
the same way: past the text is out of range, and an end before its start
is out of order. fs.md says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
as typed
`Restore x.dump.zon` read the DumpDir's x.dump.zon but logged
`restore x.dump.zon`, and `~/d.zon` logged the tilde. A follower could not
tell which file was restored. The builtin now resolves the name once
(fs.restorePath: `~` expanded, a relative name the DumpDir's when one is
there, else the current directory's) and hands that path to the host,
which reads it and logs `restore <path>`. Its messages name it too.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
4096 bytes fits
`echo <4096 bytes> > tag` wrote 4097 bytes and was refused "over 4096
bytes", although a rewrite drops that one trailing newline and would have
held exactly 4096. The limit now counts a truncating write's text without
the newline it drops, for a pane's, a column's and the workspace's tag. An
append still counts its newline, which it keeps.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
by this diff", the diff --git and --- lines too
In a section that deletes its file, a look at a removed or hunk line said
"<file>: deleted by this diff". The `diff --git` and `---` lines said "no
such file here", because they come before the `+++ /dev/null` (or
`deleted file mode`) that says so, and the walk had not reached it yet.
They now look ahead within the section, so every line gives the one
message.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
to, as acme's expand does
`ML960 960` or `MX1 1` written back with no text acted on the empty range
between the offsets: a look of nothing, an exec of nothing. A click at a
point expands to the word or file name under it, and acme's written-back
event does the same. It now expands with look.expandedWord, as a no-drag
click does, on its line of the body or tag. fs.md says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
click does
A program that set DECSET 1004 heard `CSI O` and `CSI I` when the keyboard
moved by a click, a key or the window's focus, because update() checks
after each event. A /focus write went through serveFs, which never did,
so the program kept believing it had focus until the next input event.
serveFs now runs the same check once a request has settled.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
before each timestamp into blanks
A `---`/`+++` path was cut at the tab before diff -u's timestamp. Run in
a command pane, the terminal had turned that tab into blanks, so the name
took the timestamp with it and a look at a changed line opened nothing.
The name is now also cut where blanks run up to a timestamp, either GNU
diff's `2026-09-30 10:00:00...` or ctime's `Wed Sep 30 10:00:00 2026`. One
blank is enough, since a tab can expand to a single blank, and the stamp
is strict, so a name with blanks and no stamp after them stays whole.
Tested on the parsed text and, in fs.py, on real `diff -u` output in a
command pane, where a look at `+TWO` opens the new file.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
looked for as written
Every line written to look or exec went through Messages.next, which
trimmed blanks from both ends. A look of ` indented` then found the
first bare `indented`, and a diff's blank context line ` ` looked at
nothing. A look's line is now its text: only its `\r` and newline go.
lookAt keeps the blanks for the word search too; it expands `~` only for
a look that starts with one, and the path, address and command readings
trim for themselves as before. runSearch keeps a pattern's blanks, since
a builtin's argument comes trimmed already. An exec line is trimmed as
before. fs.md says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
before throwing its text away
A dump keeps a pane's text. Restored after its file was deleted, the pane
came back clean: the watch's baseline read of the missing file failed
quietly, and Del closed it without a word. Its text was then nowhere at
all. Restore now checks the file: a local path with nothing on disk comes
back as one deleted on disk, as the watch would have said. It says so
once, logs `changed N deleted`, and is dirty, so Del, Exit and Restore
ask first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
never to the end of the write
writeData, flushBatch and writeBody showed what they wrote with
showOffset, which put the cursor at the write's end. The cursor is dot's
head, so a data write or a body append moved dot there, and a `sel` write
after it replaced the wrong text. showOffset now scrolls the view to the
offset and leaves the cursor, pinned, where it was. Dot shifts only by
the rule it already followed, acme's: an insert before dot shifts it, one
at its start or inside it grows it, one at its end or after it leaves it.
The test covers each case, then a body append followed by a sel write.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |\ \
| | |
| | |
| | | |
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
reach a terminal's program, which they never did; every key a program gets follows its cursor keys' mode and kitty keyboard flags, pinned for both shells
The keys went through ghostty's encoder already (DECCKM, the kitty flags);
the GUI's native key map simply dropped the function and editing keys it
did not name.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
2004, and the control bytes a paste could smuggle a command in by, ESC first, become spaces, so no ESC[201~ in the text ends the brackets early
Every paste path goes through edit.typeToTty (the GUI's and the tty's
paste, p from a register, the acme chord's paste, a REPL's send), which
now takes ghostty's paste encoder. A 9P write to a terminal's body or
pty/data stays typed input, not a paste. The GUI test shell's stdin now
takes a bracketed paste as one paste, as the tty does, not as keys.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
takes the keyboard and CSI O when it gives it up, to another pane, a tag or another window
The core has a window-focus event now, from SDL's window focus and from
the tty's own focus reports (vaxis turns 1004 on outside); the detached
wire carries it: version 10. The test shell's ESC]777;mouse;focus;<1|0>
fakes the window's.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
grid, in the format it chose; Shift keeps pardes's select, execute and look, and chrome is never the program's
Presses and releases under 1000, drags with a button down under 1002,
every move once per cell under 1003, X10 presses under 9, in raw terminal
input only. A press the program took keeps its drag and release, reported
clamped to the grid's edge wherever the pointer goes. The press also makes
the pane the active one. docs/tags.md says so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
tty's input; a program's wheel report carries them as xterm counts them, and Shift keeps the wheel pardes's own scroll
The reports are ghostty's encoder now (shift+4, meta+8, ctrl+16), with the
mode and format ghostty tracks. The detached wire carries the two new
bits: version 9. The test shell's ESC]777;mouse takes an optional fifth
field of modifiers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
new line, the line itself
In a diff pane (a .diff/.patch file, or a command pane's diff output), the
look's own expansion, which its hover shows, takes a whole line for a
`diff --git`, `---`, `+++` or `@@` line wherever the pointer is on it,
markers included, and for a hunk line when the pointer is on its `+`, `-`
or space. Then the look opens the file (a/ b/ dropped, timestamps cut) at
the line from the hunk header and the lines above it: `@@` the hunk's
first new line, context and added lines their own, a removed line the new
line now where it was. `diff --git` and `+++` open the new file; `---` the
old one, unless the `+++` under it names another. On a hunk line's code
the expansion is its words, the prefix never one of them, and looks as
ever. Other panes are untouched.
Paths resolve in the repository (walking up to `.git` or `.jj` from the
diff's directory, or a command pane's), then that directory. A file not
here opens nothing and says `Look: b/x: no such file here`, or `deleted by
this diff`. A 9P look writing a whole line of the diff does the same.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
and removed rows tinted
A .diff or .patch pane, and a command pane whose output is a diff (`git
diff`, `git show`, `diff -u`; told by a `diff --git` line, or `---`/`+++`
with a `@@` under them, in its first rows), colour each hunk's code in the
language of the file its section names (`+++ b/<path>`, `--- a/<path>` for
a deleted file), with tree-sitter, as highlightLocations does for results.
src/diff.zig walks a unified diff by its `@@` counts, so a removed line
that reads `--- x` is no header. Each side of a hunk is parsed as one text
(context and removed lines the old side, context and added lines the new),
so a string or comment across lines colours as it does in the file; a side
no line takes its colours from is not parsed. A section's hunks share a
parse, in pieces of about 40 lines (a hunk past 80 is cut), only those in
view, and each piece's colours are kept by its bytes, so scrolling back and
a terminal's every repaint parse nothing again.
Added and removed lines carry a flag in their style byte; the painter tints
their rows to the pane's edge, a little way from the page toward the
theme's ANSI green or red, and draws the prefix in that hue pushed to read
on it. A file in no known language keeps the old line colours.
A command pane is read once its command has finished: its rows are copied
once (File.DiffOutput, dropped when the pane runs again), so no frame dumps
the scrollback, and painted over what git printed. A running command is
shown as it prints.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
one that fills its Twrite does: a burst through a mount no longer runs its cut lines as two commands
selfmount's 1000-line burst reported 943 lines, on main too. The log
ring was not losing records: a follower opened before the burst heard
exactly 943 and no `lost`, and the burst itself exited 1 with
`err 1 exec: wrong #args in control message "Msg"`. `seq ... > exec`
through the mount arrives as stdio's 4096-byte writes, each shorter than
a Twrite. The rule that such a write is whole ran each one's cut last
line at once, so both halves of the line ran as commands (hence `exit
127` records). At 12288 bytes the cut left a bare `Msg`, which was
refused and failed the write and the rest of the burst.
A write of a multiple of 4096 bytes is where a writer's buffer (stdio, a
page cache) filled, so it may go on: its unended tail now waits for the
next write or the close, like one that fills its Twrite. `printf Save >
exec` stays whole at once. fs.md says so, the 9P fuzzer's model of served
lines follows it, and a unit test cuts a `Msg` at 4096 bytes.
A follower does not lose records silently: a ring that outruns one
already reads it `lost N` first (documented, tested). selfmount now
follows the log from before the burst, so it checks every line heard
once, in order, or a loss said, not a fresh open of a 64 KiB ring. It
passed 3 in 3 and joins the gates with the new 9ns.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |\ \
| | |
| | |
| | | |
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
however far into exiting it is
host_io's "a background job is not the tty's owner" failed now and then,
2 runs in 20 under load, always just after `kill %1`. The probe walks the
shell's children and reads each one's exe. A killed background sleep, in
the moment it is exiting (its exe link gone, not yet a zombie), has no exe
to read and is not a zombie to skip, so the probe called the tty taken.
A process outside the foreground process group holds nothing whatever
state it is in, so one whose exe cannot be read is now skipped when its
group is not the foreground one. Under the same load the test passed 50
runs in a row. The unit-test step's perf gate trips under that load,
which is not this test.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
its own and renamed into place
A client that waits for the socket file and then connects, as fs.py's
session helper and scripts do, was sometimes refused under load. The
listener bound the socket at its final name, so the file existed a moment
before listen(2), and a connect in that window got ECONNREFUSED. Now it
listens under `<name>.<pid>`, is chmodded, then renamed over the final
name, so that name only ever names a listening socket. A final name held
by a live listener is still refused, and a name with no room for the
suffix is bound in place as before. The registry test checks the socket
is listening where it appears and that the temporary name is gone.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
pane closed before it looks is done, not a failure
fs.py's `pardes --wait 'wait new.txt'` failed two runs in three on the
0.0.8 merge. The stress case repeats the test's steps: 4 of 50 failed
under load, each with "pardes: --wait: no pane shows that file". A new
name's launch makes its pane, names it, then found it again by path in
/index. The script had already seen the name, saved and removed the pane
by then, so the lookup missed and --wait exited 1.
Now the launch hands --wait the serial pane/new gave it. After a look,
finding no pane on the file means that pane is already closed, which is
the end --wait waits for: exit 0. The follow with its /index recheck
covers a close in between, as before. Under the same load the stress
case went 0 of 100.
The same load showed a test race too, at fs.py's second Restore. The
exec write is answered before the hang-up, but the client's clunk after
it can meet the connection already cut. The test now requires the
answer and tolerates the reset.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
that takes one, through one helper
Only DumpDir (dump.zig) and ShaderBuild expanded `~/`, each its own way.
So a look at `~/notes.txt`, `name ~/x`, `Save ~/x`, ThemeFile, Restore and
a quoted `pardes '~/x'` all took `~` as a directory of that name under the
pane's. There is now one rule, filesystem.expandHome. A leading `~`,
alone or before `/` or `:`, is $HOME, else the passwd entry's home;
`~user` is that user's (getpwnam). As in a shell, it applies even beside a
file named `~`, and `./~` names that file. Every entry point runs its
typed path through it:
- look, B3 and 9P, before any parsing, so `~/x:12`, `~/x:12:3` and
`~/x:/re/` all work;
- name, and a tag's rename;
- Save <path>;
- ThemeFile, DumpDir, Restore and ShaderBuild's shader files;
- the forwarding launch.
Recent rows are not shown with `~` and need nothing. How names are shown
is unchanged.
Tests: expandHome's cases, and HOME unset (passwd), with HOME passed in
rather than set, since setenv moves the environ a spawned child reads.
fs.py covers Save into missing directories under `~`, `name ~/x`, a look
at `~/x:3`, and a forwarded `pardes '~/x'`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |\ \ \
| |/ /
|/| /
| |/ |
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
report when it tracks the mouse, arrow keys on the alternate screen with alternate scroll, so codex, htop and less scroll
codex 0.158 moved its chat onto the alternate screen with any-event SGR
mouse tracking (1049, 1000/1002/1003/1006, 1007 off); its sign-in screen
keeps 1007 on with tracking off. pardes never forwarded a wheel to a
program, only scrolled ghostty's scrollback, which the alternate screen
does not have, so the wheel did nothing there. A shell on the main screen
still scrolls its scrollback as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
through pty/run goes from over 30 s to 11 s
Profiling the 50 MB run showed 70% of its time in draw.render,
recolorAnsi alone 43%, walking cells through PageList.pin. The detached
session drew a frame after every pty read, with no client attached to
see it. A host now says whether anyone watches (Host.VTable.watched). The
detached server answers whether a client is attached, and while none is
the core keeps the frame owed instead of drawing it. A /screen read draws
its own, and a client attaching gets one (hello sets needs_frame).
Debug, 80x24: 10 MB went from 7.36 s to 2.10 s, and 50 MB from over the
30 s client timeout (about 37 s by rate) to 11.08 s. What is left is the
terminal's own parsing and scrollback growth. A session a frontend shows
still draws after every read. Pacing those frames is the next step if
that case matters.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
acme's placement does
A pane/new whose column had no room was refused "no space for a pane in
that column", even with another column holding a tall pane that could
give rows. acme takes rows wherever a window has them before saying
there are none. pane/new now tries the other columns as +Errors already
did: an empty one, else its tallest pane's bottom half, last column
first. It is refused only when no pane anywhere can give the rows.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
succeeds, as bare Kill does
Bare `Kill` with nothing running is a message, not a failure: a script's
Kill has nothing left to do. `Kill make` in the same state failed the
write with "no running command has that first word", as though make were
the mistake. With nothing running at all, named or not, Kill is now the
message. It still fails when commands run but none has the word. The two
tests that used `Kill zzz` as a builtin that always fails now use
`Unmount zzz`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
other line file's last line is
`printf 'MX0 10' > event` was refused as a malformed record, while exec,
look and every ctl take a last line with no newline. The event file now
does too: a write not ending in a newline is read as though it did, and
the write still counts the bytes that came.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
err record says tag: once
The refusal's text began with "tag: ", and the log's err record puts the
file's name before the reason. So the record read `err - col/1/tag: tag:
no space: over 4096 bytes`. The text is now the reason alone, as the
control-character refusal's is, and the record names the file once.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
and Save path alike
Whether a Save made missing directories depended on how the name had
come about. Config's pane did, a name written into a missing directory did
(since kkrqxtsp), and `Save path` and every other name did not, failing
ENOENT instead. There is now one rule: a Save makes the parent
directories of the file it writes, a pane's own or a terminal's
scrollback included, and the make_dirs flag is gone. A directory it
cannot make still fails the write with why, as fs.py's
/nonexistent-pardes-dir case shows. fs.py now also saves into missing
directories by Save path and by a written name.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
addr refuses a column 0 with EINVAL, "address out of range: a column
counts from 1". A look took `file:3:0` as line 3 with no column, since
the parser holds no column as 0, and succeeded. Now a look whose column,
or end column, is written as 0 is refused with addr's words and errno.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
runs as nothing at an exec, a ctl or the init file
DumpConfig's information lines ("Platform: tty", "Startup config: ...")
began with words. Written back, as the report means to be, or clicked,
each ran as a shell command or failed as an unknown control message.
Each now starts with `# `. A line starting with `#` is a comment, as in a
shell: it runs as nothing, silently, at an exec, at the root's, a pane's
or a column's ctl, and in the init file. Documented in fs.md and
config.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
4096x4096 as the docs say
`winsize 20 1` was taken and quietly raised to 2 rows, so the write
succeeded with a size other than the one asked for. The range refusal
also said "1x1 to 4096x4096", although fs.md says at least 2 rows. One row
is now refused with "invalid winsize: at least 2 rows", and the range
text starts at 1x2. size already refused anything under 20x6 with a text
that names it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
empty whole
pty/run reads a command's output between its C and D marks. When the
end landed at or before the start, it answered `exit 0` with no output,
as if nothing was printed. That happens when the shell redraws its prompt
over the output, as it can in a window two rows high (winsize 10 2). Now
only equal marks mean nothing was printed. An end at the top-left cell
or above the start says `cut`, since how much was printed is not known.
bash, fish, long lines and 3000-line outputs at winsize 10 2 all came
back whole on this build, so the dogfood's loss could not be reproduced
directly. The test drives the marks into the inverted case the loss
needs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
command in the session's directory
/look and /exec run at the active pane, and with every pane closed they
failed ENOENT, "file does not exist", about a file the writer never
named. Now an exec runs as the workspace tag's would, in the session's
directory: a builtin at the stand-in, a command in a command pane. An
empty window's click now runs a command line too, not only session words.
A look runs from a scratch made as New makes one, which also makes the
column. That scratch is dropped, unannounced, when the look went to
another pane, so opening a file leaves only the file.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Each query kind found its own output pane by its origin. So Lspinfo and
Lspwhy, which both write `<dir>/+Lsp`, opened two panes of the same name
in one directory, and so could a code action list or a format diff. The
language server's prose now shares one +Lsp per directory, the way the
file searches share one +Search, and each answer replaces the last.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
it is run
Lspwhy kept the last query's kind and argument, but ran from another
pane it asked in that pane's file at its cursor. So it narrated a
different lookup from the one that failed. When the pane the query was
asked in is still open, Lspwhy now asks in it, at the query's offset,
whichever pane it is run from. With that pane gone, it falls back to the
pane it is run in.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
and spends no column serial
Newcol tries its column before keeping it: the new column is inserted,
the panes' rows are shared out again, and where a pane would be left
under its tag and two rows the column is taken back. The trial showed.
insertColumn logged `newcol N` and the take-back `delcol N`, so a
follower saw a column come and go around the err. Laying the column out
also gave it a serial, so the next column made skipped one. The trial is
now unannounced, since insert and drop have unlogged forms. A refusal puts
the serial counter back where it was, after first giving every existing
column its serial so the trial's is the only one spent. Only a column
that stays is logged, and it gets the next serial.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
waiting: 128", and a mount beside 40 held event reads still answers
Two limits met. pardes parked 32 reads per connection and refused the
next with EAGAIN's C string, "Resource temporarily unavailable". 9ns kept
32 tags and 31 workers, each pinned by a held read. So 31 followers
through one mount took every worker, and `cat layout` then queued for
ever: the whole mount deadlocked.
cloud9 (705be665, pushed to sr.ht and pinned here) now refuses in words
past the cap. Its 9ns window is 256, so a mount always has workers past
what pardes holds. pardes raises its cap to 128. fs.md documents the limit
beside held reads. selfmount.py holds 40 event reads through the mount and
reads layout beside them. It times out with the 9ns installed before this
change and passes with the new one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A nested pardes killed in a pane died with the default action. That left
the pane's terminal on the alternate screen, in raw mode, with mouse and
paste reporting on, so the shell under it was unusable until a reset. The
tty frontend now handles both signals: it writes the resets a clean exit
writes (keyboard protocol, mouse modes, focus, bracketed paste, SGR,
cursor, main screen) and restores the cooked termios, all
async-signal-safe. Then it dies of the same signal, since SA_RESETHAND put
the default back. fs.py kills a tty session with each signal and checks
for the main-screen switch and cooked mode; it fails without the handler.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
editor: the refusal is printed, exit 1, and no stray pane is left
When the environment named a live session that answered, several
failures broke out of forwarding and started a whole editor inside the
pane that asked: a refused name, a pane the session has not, a failed look
write. Its screen was drawn over the shell. Now, once the session answers
(Client.probe), every refusal is printed as `pardes: <file>: <why>`, in
the session's own words (the Rerror, now kept by the client), and the
launch exits 1, as acme's B does. A new name the session refuses deletes
the pane made for it, so no empty +New is left. A missing environment or a
session that does not answer still starts a separate editor. fs.py checks
a refused name and a stale PARDES_PANE.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |/
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
its square: ?a? over 117 KB goes from 6.4 s to 0.03 s
The 9P fuzzer (seed 124) hung a session for over 5 s on `?a?` in a
117 KB file of one line. A backward search is every forward match up to
the limit, so Regex.find ran once per match. Each call looked back from its
start to the line's start, and forward to the line's end, over the whole
line each time. That is quadratic, and the step budget, which counts only
mvzr's steps, never saw it. find now keeps where it last learned a line
starts and ends in the same text, and looks back only to there. The
literal prefix's look back stops at the known part of the line.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|