summaryrefslogtreecommitdiff
path: root/docs
Commit message (Collapse)AuthorAge
* docs: what dogfooding asked of the second roundGabriel Schneider37 hours
| | | | | | | | | | | | The served README, the skill and docs/fs.md now say where an address search starts, that an event record's text may hold newlines and is read by its count, that truncating tag clears its default words too (append to keep them, u in the tag to get them back), how Dump and Restore behave and where dumps go, that Kill stops only the foreground job (the rest of 'sleep 30; echo done' still runs) and that Joincol needs a column to the right. The skill and fs.md had Collapse as a column word; it folds the pane it is given. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* With no frontend attached, a detached session's messages go after MessageLingerGabriel Schneider37 hours
| | | | | | | | | | | | A message lingers until input dismisses it, and a detached session with nobody attached has no input: its messages, and /screen, kept what was said long ago. The session now marks the core unattended while no client is attached, and the core drops a pane's messages once the newest has been up MessageLinger on the clock, checked as it is stepped or served. A pane's older lines go with its newest rather than each on its own clock; the render pipeline's clock is the place for that. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Joincol with no column to the right and Theme with no such theme say soGabriel Schneider37 hours
| | | | | | | | | | | Both did nothing without a word, from a click or a ctl write alike, and a script could not tell a no-op from success. Joincol in the rightmost column now fails 'Joincol: no column to the right'. A Theme name that is none says so and names the themes sharing its first letter, since all of them (ThemeSel lists them) are too many for a message or a refused write; a startup config line still fails quietly, as its other bad lines do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: through a mount a malformed write is EINVAL and one that fails is EIO, ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | and the error words keep it so The served README said every refused write reads as EINVAL, but a mount's errno is 9ns's reading of the error's words, so a no-match or out-of-range address and a refused Exit came back EIO, as the dogfood run saw. That split is the useful one, malformed against failed, so the docs now state it rather than the words being bent to EINVAL; a test pins each error's words to its side of it. It caught one: 'regular expression search took too long' read as ENAMETOOLONG, and now says it gave up past its step budget. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The root look and exec read back what a ctl write touched tooGabriel Schneider37 hours
| | | | | | | | | After a pane made by Tty or Newcol written to a ctl, /look and /exec still read the serials of the last look or exec, and a script took the old pane for the new one. A ctl write now resets them and records what each line made, or else the pane it ran at, as a look or exec does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An address searches back after a minus, and a range ending before its start ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | is refused -/re/ searched forward, since only ?re? set the direction, where acme's address() takes the direction a minus set (addr.c). And #100,#50 was taken, leaving data to act on an empty range at 100; sam refuses it as 'addresses out of order', which acme leaves out, and so does pardes now. The rest of the dogfood report on addresses already held and is now tested: an expression is evaluated from the current address, as acme evaluates it from w->addr (xfid.c:446), so a search starts where the last address or data write left it and . is that address. Taking . as the selection instead, as the report asked, would part from acme, which has dot only in its ctl messages; the docs say which is which. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A click that takes no text tells the event reader nothing, and click records ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | are tested for their offsets Dogfooding saw a body right-click reported as ML0 0 2 3 qty. On file panes the offsets were right in every case tried here (a scratch made over 9P and clicked while another pane is active, after a hover, scrolled, soft-wrapped, tab-indented, inside parentheses); the test now holds them. The 0 0 form is a terminal's body, which has no offsets to give (its body is a history snapshot); since the event file now takes a record back whole, such a record can still be written back and done, and the docs say so. What the test did find: a click on whitespace sent an empty record, where acme's look3 and execute return without a word on an empty expansion (look.c:37, exec.c:141). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A line written to a pane's own look or exec goes to the event reader holding ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | the pane A script writing to pane/N/exec bypassed the client holding that pane's event file, which a middle click on it would not: acme sends a window's clicks to its event reader (look.c:53, exec.c:173). Such a line is now an F record at 0 0 carrying its text; the root's look and exec still act at once. acme takes back only origin, action and range, which a record with no place in the text cannot use, so the whole record as read is taken too, and for an empty range acts on its text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A Restore answers its writer before hanging up, and the log records dumps ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | and restores A client that wrote Restore saw its connection cut with no answer, and could not tell a Restore from a crash. The listener now lets the writer's answer out before the cut, and cuts only the old editor's connections, refusing their requests meanwhile; a client that dials during it is the new editor's and stays. Dump logs 'dump <path>' and the restored editor's log 'restore <path>'. Keeping connections across a Restore was weighed and left: the fids name the old editor's panes and opens, so it would mean carrying serials and open records into the new one, where acme's Load only adds windows. tty's Restore also closed its shells' ptys without reaping them; it retires them now. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A regular expression search is bounded by a step budget patched into mvzr, ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | not windows and a repeat cap The windows returned wrong matches: a candidate reaching a window's edge was left to the next window, half a window on, which could answer a match starting mid-token rather than the leftmost, and addr then pointed data's next write at the wrong bytes. The repeat cap missed mvzr's own worst case, a chain of a?, and alternation under a repeat, each exponential inside one mvzr call the deadline could not interrupt; and it refused ordinary s/S patterns. build.zig now patches the fetched mvzr at build time with a step counter on its backtracking recursion (matchPattern), so a fresh fetch keeps it and a moved anchor stops the build; regexp.zig gives each compiled pattern a budget, about 300 ms here, and a search that spends it fails as taking too long. Windows, the cap and their special cases are gone, and matches are exact again. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An Exit or Restore refusal says the same word again discards the textGabriel Schneider37 hours
| | | | | | | | | | '<name>: Modified' read like a failure to retry, and a script that retried Exit or Restore threw the text away without knowing it. The refusal now names the word asking and what repeating it does, '<name>: Modified (Exit again to discard)', and the skill sets it apart from lock's 'file in use', which is the one to retry. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Restore asks about unsaved text first, as Exit doesGabriel Schneider37 hours
| | | | | | | | | | | Restore replaces every pane with a dump's, so a pane edited since its last save lost that text without a word, where Exit asks. acme's Load only adds a dump's windows and so never asks; Restore now asks what Exit asks (acme's rowclean and winclean, wind.c:511-529): each modified pane says so once, and Restore again with nothing edited since goes ahead. Exit and Restore share the check and its warned-at revision, as acme's winclean clears one dirty flag for any asker. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: data's truncation is pardes's own, a second write inserts, and a ↵Gabriel Schneider37 hours
| | | | | | | | | | | | waiting pty/run is cancelled Review asked the docs to say what a script trips on: acme ignores OTRUNC on data (fsys.c:543), so truncating it is an extension; addr sits past each write, so a second echo x > data inserts after the first; and a pty/run line waiting for a fresh terminal's first prompt waits for ever if none is drawn, so the way out is to interrupt the read. The lock's retry advice was already there. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A repeated err record in the log is the newest record counted, not another lineGabriel Schneider37 hours
| | | | | | | | | | A client retrying a write that fails the same way pushed one err line after another until the log's ring held nothing else. The same err as the newest record is now that record with a count, (x4), as +Messages counts repeats; a follower that has already read the record still gets each repeat as its own line, since it may be waiting on exactly that. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Kill asks the host to signal at once and says when a shell has no job to signalGabriel Schneider37 hours
| | | | | | | | | | | Kill queued a signal effect for later, so the job it saw running by its marks could have ended, and another started, before the signal went; and with job control off the job shares the shell's process group, so the host skipped it and Kill reported nothing. Kill now calls the host's kill_job while it holds the turn, and when the only job is the shell's own group says 'Kill: no job to signal', which also fails a write of Kill to ctl. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A regular expression search comes back: costly patterns refused, long lines ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | windowed, 300 ms deadline mvzr backtracks with no bound on its work (a*a*a*a*x over a hundred a's takes a second, each repeat multiplying by the haystack length), and a search runs holding the editor's turn, so one pasted pattern froze the editor. pardes does not write or vendor a regex engine, so regexp.zig bounds what it hands mvzr: more than four repeats is refused, a line longer than a window sized from measured worst cases is searched in half-overlapping windows, and a deadline stops the search. addr names each failure; normal s/S keeps what it found. The prescan also stops reading an escaped backslash before n as a newline, and ends a class where mvzr does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Exit quits and Kill stops commands, as in acmeGabriel Schneider37 hours
| | | | | | | | | | | | | | | | Kill quit the editor, which in acme is Exit; acme's Kill stops the commands it started. Exit now quits as acme's does (exec.c, rowclean): it refuses once, naming each pane with unsaved text, and quits when asked again with nothing edited since (a small scratch is not asked about). Kill, bare or with names, stops the commands pardes typed into a terminal (an exec, a middle click, a pty/run) while their shell's marks say they run, by SIGTERM to the terminal's foreground job, never to the shell (acme posts the kill note, which terminates). Both are session builtins; the topbar's Kill becomes Exit, same width, and every golden's topbar row changed by exactly that word (checked line by line); the builtins script scrolls one more row for the index's new line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Normal mode's s and S search as addr does, through one shared regexp.zigGabriel Schneider37 hours
| | | | | | | | | | | | The sam-style calling convention for mvzr (a line per haystack, . made [^\\n] only when a pattern names \\n) lived in addr.zig; normal mode's s and S called mvzr over the raw selection, where ^ meant the selection's start and . crossed lines. src/regexp.zig now holds the one Regex (compile, find) both call, and fs.zig and pardes.zig drop an unused mvzr import. hxdiff and hxparity stay at their known 17 and 6 mismatches, none of them regex cases. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: the README and skill answer what dogfooding askedGabriel Schneider37 hours
| | | | | | | | | | | | A first-time user through a mount could not find how to get a terminal, read path++text as a typo, did not know > on data replaces only the addressed range, which regexps addr takes, that lock fails fast, what errors is, where an unknown exec word goes (typed into a terminal, not an error), that new panes are +New and a column's last pane leaves one, or which 9ns mount other processes can see. The README (still 45 lines), docs/fs.md and the skill now say. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A refused or failed write is an err record in the log, naming the file and ↵Gabriel Schneider37 hours
| | | | | | | | | | | | the reason Through a mount every refusal reads as Invalid argument, so a shell user could not tell a missing regexp match from a bad ctl word. Every write or truncation the tree refuses or that fails now adds err <serial|-> <file>: <why> to /log. No per-pane readable error file: acme's errors only takes text, and one stream is simpler to watch. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A terminal's new directory is a rename in the log, and its ctl counts its bodyGabriel Schneider37 hours
| | | | | | | | | | The log said new N / and later del N <cwd> for a terminal, with no rename in between, though a terminal is named by its directory. setCwd now logs the rename once the pane has been announced. A terminal's ctl line gave body length 0 while its body reads its history; it now counts that history (without keeping a copy). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A lock another open holds fails at once with file in use instead of parkingGabriel Schneider37 hours
| | | | | | | | | | | A contended lock parked until the holder unlocked, but through a kernel or FUSE mount the kernel serialises writes to one file, so the parked lock held up the holder's own unlock and close on that ctl, and the two deadlocked. acme's qlock blocks; here the second lock is refused at once with file in use (EBUSY) and the client retries, and nothing parks on the lock any more. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pty/run on a fresh terminal waits for the shell's first prompt instead of ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | answering busy A new terminal's shell takes tens of milliseconds to draw its first prompt, and a run written meanwhile answered busy, so a script's first command was lost, while pty/status said busy 0. A line written before the first prompt now waits for it and is sent then (a respawn in between keeps it waiting for the new shell), and pty/status's third field says what a run would be told: busy while a command runs or text is typed at the prompt, not before the first prompt. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Addresses search a line at a time as sam does, say why they fail, and a ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | failed addr leaves no address addr's regexps ran mvzr over text[from..hi]: ^ and $ anchored only at the slice's ends, . matched newlines, the search never wrapped, and every failure read as bad address syntax. The regexps stay mvzr's, called the way sam searches (editors/acme/regx.c): one line per haystack, so ^ and $ fall at line boundaries and . never crosses a newline; a pattern naming \\n runs over the whole text with its . made [^\\n]; /re/ wraps unless limit is set, and ?re? takes the last match before the range. The ceiling (mvzr's first alternative, not sam's longest) is documented. A failed address says why (no match for regexp, address out of range, bad regular expression), and a failed write to addr leaves no address, so data and xdata refuse until the next good one instead of writing at the old range. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Truncating data or xdata deletes only the addressed range, not the whole bodyGabriel Schneider37 hours
| | | | | | | | | | | A shell's echo NEW > data opens data with OTRUNC, and truncate() spliced the whole body away before the write replaced the addressed range: a five-byte replacement erased a buffer. data and xdata hold what addr names, so truncating one now deletes that range and nothing else; > on data replaces the range and : > data deletes it, and only truncating body clears the buffer. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: Kill quits the editor, and the column words are a pane'sGabriel Schneider37 hours
| | | | | | | | | Kill in pardes is acme's Exit, not acme's Kill, which only stops commands; the README, docs/fs.md and the skill now say so where the root ctl lists it. Delcol, Collapse and the other column words take a pane's ctl and act on that pane's column; Newcol and Joincol are the root's. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Focus gives the keyboard only, reads empty while a header has it, and sits ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | in the root listing's natural place A write to /focus leaves a folded pane folded, as rio keeps current apart from unhide; while a column or workspace tag has the keyboard no pane does, so /focus reads empty and every pane's ctl says notcurrent (an empty read also no longer answers stale staged bytes). focus, ctl and commands now list after status, and the discovery test checks the root as a set rather than by position. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: record dogfood evidence on unknown exec words in the open questionsGabriel Schneider37 hours
| | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A ctl write fails when a builtin it runs fails, and a missing required ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | argument is refused before anything runs A ctl write failed only on a malformed line: Mount x reported its error in the editor while the write succeeded, and a bare Mount failed only as it ran, after earlier lines of the write. acme's ctl answers a command's error (editors/acme/xfid.c:700). Builtins now declare requires_arg beside takes_arg (settings: those with a value to set), and the check refuses a bare one as wrong #args before any line runs; while a ctl runs, the first error a builtin reports fails the write, quoted with its line, and the prompt refusal quotes its line too. Docs say what a failure mid-write leaves done. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A root commands file lists every builtin, its argument and which ctl takes itGabriel Schneider37 hours
| | | | | | | | | A script could learn the builtin words only from source or the Help window. /commands is generated from the registry: one line per builtin, Word or Word arg, then root or pane for the ctl that takes it, so it is always this build's own list. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Split control messages by scope: the root ctl takes the session's builtins ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | and reads the settings, a pane's ctl its own Every builtin could only be clicked, or written to exec, and the settings could be read only as the Config window's prose. acme keeps window verbs on a window's ctl, and webfs and upas/fs keep session settings on a root ctl. Each builtin now declares its scope (scope = .session; settings are all session, the rest pane), read by the registry. The root /ctl takes session builtins and reads every setting in the words a write takes, so its read written back changes nothing (panel and scene effects now take on/off like the toggles, to make that true); a pane's ctl takes the pane's builtins beside get, lock and unlock. Writes are checked whole and refused in Plan 9's ctl words (unknown control message "X", wrong #args ...), which 9ns now maps to EINVAL (cloud9 re-pinned at a8c7a715). A builtin that would prompt for its argument fails the write instead, and a refusal is answered at once, not after the frame. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A root focus file names the pane with the keyboard and moves it; a pane's ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | ctl says whether it is current Scripts had no way to ask which pane has the keyboard or to give it one. rio answers both through a window's wctl: its read ends with current or notcurrent, and a write of current takes the keyboard (rio(4)). A pane's ctl line now ends the same way, and since there is one keyboard for the whole tree, /focus reads the focused pane's serial and takes a serial to move the keyboard there, off any header that had it; a serial no pane has fails with "no such window". fs-bench's stale readdir check is fixed too. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: the render pipeline design, with the user's decisionsGabriel Schneider37 hours
| | | | | | | Designed by two agents (a designer and an adversarial reviewer) and not yet implemented; implementation starts in stages, each its own change. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Let the keyboard reach a tag's path, read-onlyGabriel Schneider37 hours
| | | | | | | | | | | | | | The tag's computed path, dirty marker and page were out of the keyboard's reach: its cursor lived in the text after them. It now lives in the tag as shown, as in acme where the name is ordinary text at the start of the tag, so `0` goes to the line's start and motions select and yank the path. The path stays read-only: an edit that would change it is refused and leaves the cursor where it was, and typing into a file's path drafts a new name as a click on it does. Sync moves the tag's positions when the prefix changes length, so a rename or the dirty marker still never moves the cursor off the text after it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Let s, S and | pressed in a tag answer for the tag's own textGabriel Schneider37 hours
| | | | | | | | | | A tag is a text like the body, so selecting on a regex and piping act on the text they are pressed in: a prompt records the text it answers for, the tag keeps the keyboard while it is typed, and a header's prompt goes on the active pane's band. `/` still searches the body from anywhere, as acme's Look from a tag searches the body. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Run the word under the cursor when Enter is pressed in a headerGabriel Schneider37 hours
| | | | | | | | | | The workspace and column tags hold nothing but commands, and before they became texts Enter on one of them ran it: Enter on Newcol made a column. Since then Enter looked the word up, as it does in a pane's tag, which only searched for it. It runs it again, and the header lets go of the keyboard first as a pane tag does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Let the tag's undo bring back what a 9P truncate clearedGabriel Schneider37 hours
| | | | | | | | Truncating the tag file replaced its text without an undo point, so the cleared text was gone for good. It is recorded now like a typed edit, the history is kept, and docs/fs.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* File the tag code into tagline.zig and draw tags beside bodiesGabriel Schneider37 hours
| | | | | | | | | | | With tags reduced to Texts, what is left of them is the computed prefix, the default and saved tails, entering and leaving a tag and the headers: that goes to tagline.zig, as acme keeps the tag half of a window in wind.c. Tag and header drawing moves next to body drawing in body_layer.zig, and the tag hit helpers go to tag_layer.zig with the Hit they read, where sameCell now also tells the lines of a taller tag apart. The docs describe the tag as a Text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Give prompts their own line to type into instead of the tag's tailGabriel Schneider37 hours
| | | | | | | | | | | A search, pipe or Save prompt wrote its marker and answer onto the end of the tag, so the tag's cursor, its selection, its 9P writes and a prompt abandoned by a click all shared one buffer: the abandoned text stayed in the tag and a 9P write landed inside the prompt. The answer is now its own Text on the pane, typed in insert mode and shown on the notice band where it was already drawn, and the tag never holds any of it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Point docs and comments at the files code moved toGabriel Schneider37 hours
| | | | | | | | | | | | | Documentation only, no code change: README's reading order and layout, docs/design.typ's paragraph on where pane kinds and editor parts live, docs/helix-keys.md's code map (normalInput and the executors now in normal.zig and edit.zig, insertTab in edit.zig), docs/open-questions.md (execute and ttyForDir in exec.zig), and the comments that named pardes.zig for fold, Cell, takesCommandLine and runBuiltin (tools/gen_themes.zig, themes/helix.zig, detached/wire.zig, host_io.zig, lsp_zls.zig). docs/design.pdf is a retained fixture and is not regenerated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Answer a held read by its cloud9 ticket, refuse a second, and say a pane ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | shut down The held read is now kept by the Ticket cloud9's Conn.hold() gives its park and answered through Conn.answerWith(), which makes the answer only while that very park still waits, instead of walking the engine's slots by tag; pardes no longer reaches into the engine for it. A second read on an open whose read is held fails with file in use rather than sitting parked where nothing answers it, and a read that waits with no open record to hold it is logged and asserted on. A read on an event or pty/data open whose pane closed answers acme's "window shut down" (editors/acme/xfid.c:1005). The pane keeps its run's and its lock's open handles, checked through openOf on use, not record indices. Docs: lock from a shell needs a held fd, and a command that clears the screen may read as cut. Needs cloud9 zvuqvnzy (cca47d63), which adds Conn.hold, waiting and answerWith; build.zig.zon still pins 82d8152c until that is pushed and re-pinned. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pty/run says cut when its output's start is gone, and reads only a bounded tailGabriel Schneider37 hours
| | | | | | | | | | | | A clear or reset while the command ran, a start or end mark that came on the alternate screen, or a garbage end pin read as a complete answer; now any of them, like a start that scrolled out, answers exit N cut. The output is read from at most output_rows rows above its end instead of the whole history on the editor's thread (cut if that clips it), a D with no status answers exit ? rather than exit 0, and running out of memory answers error out of memory rather than cut. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pane's ctl takes acme's lock and unlockGabriel Schneider37 hours
| | | | | | | | | | | | A client doing an edit of several writes to addr and data had no way to keep another client's from landing in between. acme's window ctl takes lock and unlock for this (editors/acme/xfid.c:603-611): a qlock that blocks a second locker, owned by the fid that wrote it and given up when that fid is clunked, binding only clients that ask. pardes does the same: the open's record holds it, a second lock parks until unlock, close or the pane closing, and no other write is refused for it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Keep what each open holds in one table of open recordsGabriel Schneider37 hours
| | | | | | | | | | | | | Snapshots (and /log's cursor), runs, and the reader_handle constants for event and pty/data each reused the open handle and each validated handle and node on its own. Now p.fs.opens is one table of 64 records, each the node it was opened on and a tagged union of what it holds, like lib9p's per-fid aux and acme's Fid (editors/acme/dat.h:373-385): one lookup (openOf), one release, ENFILE when full. A held read lives in its open's record, so it goes with the release. Opens that hold nothing answer handle 0 and take no record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Hold a read that has nothing yet and answer it when its file has newsGabriel Schneider37 hours
| | | | | | | | | | | | | | A following log, event, pty/data or a pty/run before its answer used to answer .again and wait for a wakeAll, which only the parked-write path asked for, so the band-aid had every queue push set turn.parked. Now the core keeps such a read (ctlfs.hold) and, as the turn is given up after anything that queued a record, ran a command out or closed a pane, answers it on its own connection, the way factotum answers the log reads it keeps and acme an event read. Only a read the engine still holds parked is answered, because cloud9 tells the backend nothing of a Tflush, so a flushed read spends no record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* docs: record the open question of where an unknown command word runsGabriel Schneider37 hours
| | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pty/run answers with the command's output; pin cloud9 with 9ns concurrency ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | and E.BUSY The answer is now the header line (exit N, or exit N cut M when only the last 64 KiB were kept, or exit N cut when its start scrolled out of the history), then what the command printed: the screen text between its C and D marks, which the marks handler pins so scrolling keeps them. Also from review: a plain /log open honours its offset until follow is written, so tail -n and less work; whitespace-only run lines are refused. cloud9 is pinned at 82d8152c: 9ns keeps up to 32 requests in flight per mount so a waiting read no longer freezes the rest of it, and E.BUSY replaces the errno pardes spelled locally. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Run a line at a terminal's prompt through pty/run and read how it endedGabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | | /pane/<n>/pty/run takes factotum's rpc shape: write one line on an open, read the answer on that same open. The answer is exit N once the command ended and the shell is back at a prompt; busy at once when a command runs, text is typed at the prompt, or the shell has not drawn its first prompt; error not run when the shell refused the line without running it (fish on a syntax error keeps it on the prompt, so it is taken back with Ctrl-U); error shell gone when the pane closes or its shell is replaced; error no prompt marks for a shell pardes could not instrument. The end comes from the shell's OSC 133 marks. ghostty parses D's exit status and drops it, so the stream now runs through a handler that wraps ghostty's and follows prompt -> input -> running -> done. The marks pardes injects into bash and fish carry aid=pardes and only those count, so fish 4's own marks (which doubled ours), a nested shell's, and a stray 133;D in printed output are ignored. Checked end to end against real bash and fish: false, exit 7, a syntax error, sleep, busy while running, and the pane closing mid-command. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Wake reads waiting on /log, event and pty/data; one reader per consuming ↵Gabriel Schneider37 hours
| | | | | | | | | | | | | | | | | | | | | | file; pty/ctl reads back A read parked on a queue was retried only when some unrelated write had to wait, so a follower of /log (and a reader of event or pty/data) slept until then. Pushing a record now marks the turn parked, and giving the turn up wakes them (measured: stuck past 3 s before, 0 s after). event and pty/data consume what they read, so a second open for reading is refused with rio's "file in use" (EBUSY through 9ns); writers still get in, and pty/data queues output only for an actual reader. pty/ctl reads back "winsize C R", in the words it takes. /log fixes from review: a record longer than a read comes in pieces (a shell read loop failed on long lines), every repeated message is logged, a record bigger than the ring is cut to fit instead of emptying it, the ring is reserved at boot so recording never allocates, and panes present at boot are recorded first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Record /log whether or not anyone reads it, with the editor's messages in itGabriel Schneider37 hours
| | | | | | | | | | | | | | | /log is now one ring (64 KiB, 4 KiB on the board) that records new, del, rename and save, and a msg line for everything the editor says. An open freezes it, so cat log shows what happened lately and ends; writing follow to that same open makes reads past it wait for newer records, and a follower the ring outran reads lost N first. The message log keeps the pane's serial, not its reusable slot. A test now fails when the tree serves a file /README never mentions; it caught pty/status, now documented along with typing through pty/data. Co-Authored-By: Claude Opus 5.5 <[email protected]>