summaryrefslogtreecommitdiff
path: root/docs/fs.md
Commit message (Collapse)AuthorAge
*-. Merge: 9P rounds 7-8 + layout files + loose ends + G3 cursorGabriel Schneider33 hours
|\ \
| * | The board image links again: sources are no longer embedded by default on ↵Gabriel Schneider33 hours
| |/ | | | | | | | | | | | | | | | | | | | | | | | | esp32p4 uzksuumxruzr turned -Dembed-sources on for esp32p4 (before it, the board was the one build without them). The sources are ~1.8 MB against a 1.5 MiB app partition, so the object built but the firmware did not link: .flash.rodata overflowed by 786392 bytes and .flash.text by 1732312. Default off everywhere; -Dembed-sources=true still embeds them. Without them the image is 1459760 B, 113104 B under 1.5 MiB. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The tree's README and fs.md answer round 8's doc questionsGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | The README's log line names newcol, delcol, ask, restored and restoredcol; it says what $m is under 9ns --unix; and a build that embeds no sources no longer lists src/ (derived from the build, and tested). fs.md says what the rest of a typed line does after Kill for each shell (fish runs on, bash abandons it), that Exec <text> in a .py pane runs a command and never the REPL, and why appending to a tag wants printf and a leading blank. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A column has a ctl, an exec and an rmdir over 9P, and Restore maps its serialGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | A script could read and write a column's tag but not act on the column. col/<serial>/ctl takes Delcol, Joincol, New and Tty, each acting on that column as from its tag; col/<serial>/exec runs a word as a middle click in the tag; rmdir col/<serial> closes an empty column and refuses one with panes (ENOTEMPTY, an err record saying why). The root ctl's refusal of Delcol and Joincol points at col/<serial>/ctl. A dump keeps each column's serial and Restore logs restoredcol <old> <new>; the dump golden gains them. Documented: Joincol's survivor, the column on the right, keeps its serial and tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A terminal's body reads as logical lines, the last one ending in a newlineGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | A terminal's body came back as the screen's rows, a long line cut where the terminal wrapped it and the last line with no newline. The body (and a terminal's Save, and the length its ctl reports) now joins wrapped rows by ghostty's wrap flags, as pty/run's output does, and ends the last line with a newline. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A focus write makes its pane's column the active one, and layout's active is itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | Writing a serial to /focus gave that pane the keyboard but left the active column where it was, so pane/new under Placement acme went elsewhere, and /layout's active named the keyboard's column rather than where a new pane would go. A focus write now sets the active column as the user's click there would, under either Placement, and /layout's active names the active column, which pane/new and a look place into. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A desktop session holds 64 panes, and every route that finds none free says soGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | Sixteen panes was far too few for a real session. MAX_PANES is now 64 on a desktop and stays 16 on the board; the 48 more slots cost about 3.7 KB each in fixed tables (the core 1.33 to 1.45 MB, its surface 19 to 72 KB), and a pane itself (84 KB and its terminal) is allocated only when it opens. At the cap, pane/new fails with `pane/new: no pane slots: 64 max` and an err record rather than a bare ENFILE, a 9P look or exec that would open a pane fails its write with the same words and reads back empty, and New, Tty, Tutor and Alt-n say it on the message row (their ctl writes fail with it). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Columns are named by stable serials over 9P, as panes areGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | /col/<n> named a column by its index, which shifts when a column left of it closes: exactly what scripts trip on. A column is now /col/<serial>, its serial kept while it lives and never reused; /layout lines give serial and index (`<serial> <index> ...`), active names the serial, /index's last field is the column's serial, and the log says newcol and delcol with serials. Docs, the skill and the tree's README say so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The tree serves the layout: /layout, /tag and /col/<n>/tagGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | A script could not see where the panes sit or edit the tags a person clicks in. /layout lists each column, its index, x and width in cells, current or not, empty or full, and its panes' serials, then the active column; /tag is the workspace tag and /col/<n>/tag a column's, read and written as a pane tag is (one line: a newline written in is a space, and a truncating write drops the one ending it); /index's lines end with the pane's column; the log says newcol <n> and delcol <n>. acme serves no column files, and the docs say so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Docs answer round 7's questionsGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | The grip's two terminal cells (the mode, then * for unsaved text), a new terminal's new N / then rename and the ls it runs at its first prompt, the tag offsets an x record carries, Del k and Del j, each builtin's msg in the log and its serial, and m=$NINE_MOUNT under 9ns --unix in the skill. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A GUI-only setting says so on a terminal, and DumpDir reads back its directoryGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | `Lift on` over ctl on a terminal answered "unknown control message" while Config listed Lift as unsupported, and the ctl's DumpDir line read bare while Config showed the path in effect. A setting word this frontend lacks is now refused as `Lift is GUI-only` (GripWidth too), and DumpDir reads back the directory in effect, as Config does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A send to Python's REPL runs once, the Enter after the paste, not in itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | A one-line send (print(1)) to Python 3.14 stopped at ... and needed another Enter: its REPL takes a bracketed paste, and an Enter read in the same read as the paste is part of the paste, one line or not (checked in a real pty). Into a REPL that asked for bracketed paste, the Enters (two for an open block) now wait for its next output, its answer to the paste, or 250 ms with nothing. fs-test runs python3 in a real pty and checks a one-line exec prints at once; the docs' pty/data recipe says to send the Enter apart. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A truncating write to tag drops the one newline that ends itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | `echo X > tag` stored X and a trailing newline, which drew an empty tag row. After a truncation the newline ending each write is held back until more text follows or the open is released, so the one ending the whole of it is dropped and any other stays; `>>` keeps what it is given. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Del and Delcol refuse unsaved text once, as acme's doGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | acme's Del asks winclean first and Delcol colclean (exec.c del, delcol): unsaved text is warned about, and the same word again closes. pardes closed at once. Both now refuse once through the one-warning-per-word mechanism Exit uses, from keys, tags, exec and ctl alike. A pane dirty only by a rename, or an empty one that never held a file, has no text to lose and is not asked about, and a scratch or a command's output under 100 bytes is not either, as acme's winclean passes a small unnamed window. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Exit and Restore name a modified +New scratch too, in one wordingGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | Their refusal named only file panes, so text typed into a +New scratch went unasked about and was lost. A scratch with text counts as unsaved as a file does (acme's winclean asks about an unnamed window too). The refusal a ctl write gets now reads as the message row does, `<names>: Modified (Exit again to discard)`, instead of a second "discard them all" wording. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A choice setting's refusal names what it takes, and /commands lists themGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | Bare Placement and BootShell flip, which is pardes's convention for a word that chooses (Crt does too), but nothing said so, and "bad value in control message" never said what would do. A refused value now says `takes acme, pardes` (every switch and choice setting), /commands lists each such setting's values in a fourth field, and config.md and fs.md say that bare steps to the next. Motion and ShaderAnimation stepped nowhere bare and now step like the rest. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | An answer the question does not offer is refused, and the question standsGabriel Schneider33 hours
|/ | | | | | | | | `answer z` to a question offering a and b succeeded, sent nothing and dropped the question; so did Del's `answer x`. The ctl now takes only an offered choice or -, refuses anything else with the choices it takes (`answer takes k j or -`), and leaves the question asked. Co-Authored-By: Claude Opus 5.5 <[email protected]>
*-. Merge: 9P round 6 + empty columns + render (acme theme, grips, Lift, Motion)Gabriel Schneider33 hours
|\ \
| * | A column can be empty, as acme's can; new panes go where acme's ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | makenewwindow puts them Newcol makes an empty column; closing a column's last pane leaves it empty with the keyboard on its tag; Delcol and Joincol alone take a column away; the session's last pane closing quits. The +New stand-in and replaceStillborn / stillborn_joiner are gone. Every new pane goes through exec.placeNew, which follows acme's makenewwindow (active column, empty column whole, blank space, halving the biggest) or, with Placement pardes, the old rules. ColumnTags is gone: column tags are always shown. A grip drag shows acme's box cursor. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | fs.md answers round 6's doc questionsGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | Event origins and the case of an action (tag x, body X), printf rather than echo for >> tag, pty/run only at a shell prompt, why error not run gives no reason, how to rerun a command pane, a shell's exit closing its pane, Kill stopping a command pane's whole line, and restarting 9ns after a Restore. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Kill stops a command pane's whole line again, now it runs with job controlGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With the line run under job control (the change before), the job running has a group of its own, and Kill's SIGTERM to the tty's foreground group stopped only that job: of `sleep 30; touch x` the touch still ran. For a command pane the hosts now signal the shell's group as well, so the whole line stops, as it did; a line typed at a prompt still loses only its foreground job. The test forks a real pty for both halves: a background job outliving its command and the pty's hangup, and a killed line not running on. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A Restore logs restored <old> <new> for each paneGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | A script holding serials from before a Restore could not find its panes: the replacement numbers them afresh. The dump now keeps each pane's serial (0 in older dumps), and the replacement's log says `restored <old> <new>` for each after its `restore <path>`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A pane's question is logged as ask, and answer on its ctl answers itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A script could not answer the several-REPLs question, which only a key could. Every question a pane asks on its notice band (which REPL takes an exec, Del's side from the keyboard) is now logged as `ask <serial> <what> <choices>`, and `answer <choice>` on the pane's ctl answers it as that key would, `answer -` taking it back as Esc does. One function answers for a key and for the ctl. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A Python block sent to a REPL gets the second Enter that ends itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent's `def` sent to python3 sat open at the continuation prompt: a block whose last line is indented is not over at one Enter, pasted into 3.13's REPL or typed into the old one (checked against python 3.14 in a real pty, both ways). A send to a Python REPL now adds that second Enter, and the pty/data recipe in the docs and the 9P skill says to. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A command pane's background job outlives its commandGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent's background jobs died when the command that started them finished, even under nohup. The command's shell leads its terminal's session, and on its exit the kernel hangs up the terminal's foreground group, which with job control off is the shell's and every job's. The line now runs with job control on (bash, sh, dash, zsh, ksh -m; fish status job-control full), so a job has a group of its own and lives on, printing below exit N, and survives the pane closing. While a job holds the pty the pane is not reused, so the directory's next command gets a second pane (cmdexit's golden, re-recorded by name). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A shell that exits under a run answers exit N, and the log says exit before delGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent ran `exit 3` through pty/run: the reader got ENOENT, and the log went straight to del. The hosts now read a shell's exit status at its pty's end as they do a command's; a run waiting on the line answers `exit 3` with what it printed, the log says `exit <serial> 3` before the pane's `del`, and an open run still stats after its pane is gone (cat fstats its input). Pins cloud9 f35b7ed, whose stat of an open fid names its open. Writes to a gone pane's pty/data, held open or not, fail ENOENT. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | pty/status reads the pty's size as winsize set it, on a line of its ownGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent wrote winsize 100 30 to pty/ctl and pty/status went on reporting the pane's grid, and the status line had no newline to end it. The size winsize sets is kept until the pane resizes and gives the pty its grid again; ctl's winsize read back and status both report it, and status ends with a newline. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A look with a blank in its pattern addresses, file:N selects the line, and a ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | miss is said, logged and reads back empty Round 6: look calc.py:/return a/ was a word search, since a blank ended the address; calc.py:99 past the end focused the file and said nothing; and /look still read back the pane before a miss. A pattern after the colon may now hold blanks; file:N selects the line, newline included, as acme's does; a line past the end opens and focuses nothing; and every miss (no match, a bad address, a line past the end) says so, logs err <serial> look: why, keeps the selection, and leaves look reading back empty. Documented, with file:0/re/ for the first match, since acme evaluates the address from the file's dot. Five goldens change: a look at file:N now selects the line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A tag no longer marks an unsaved file with *: the grip shows itGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | The grip button now shows a pane's unsaved text in every state, as acme's modbutton does, and acme's tag has no asterisk. The computed prefix is the name alone, so tag reads, event offsets that count the path and the tag's text lose the " *". dirty, index's flag and the refuse-once guards are unchanged; a dump from before still restores its tags past the old mark. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A write of an Edit block reaches Edit whole, on a pane's ctl, the root's and ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | exec Every write was split into lines, so a { group or an a/c/i text block written to ctl or exec became lines of their own: i/.../ and } ran as shell command panes that exited 127. An Edit line now takes the lines after it while its group is open or its text block waits for its . line (sam_edit.needsMore, asking sam's parser), on all three; the root ctl takes Edit at the active pane. s/re/text/N counts as sN/re/text/ does. The docs and the skill show a block written by heredoc or env printf, since bash's printf writes line by line, and take round 5's doc list: get refusing once, the (xN) on a repeated err, limit bounding only a forward search's end, line:col's clamping, and $NINE_MOUNT under 9ns --unix. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | ^ in a pattern with \n matches at every line start, and a ^ or $ that cannot ↵Gabriel Schneider33 hours
|/ / | | | | | | | | | | | | | | work is refused A pattern naming a newline runs over the whole text, where mvzr's ^ is only the text's start: /^def .*\n/ from #0 failed, and Edit ,x/^def .*\n/.../ silently did nothing. A leading ^ is now tried at each line start from the search's own; $ just before \n is dropped, as it changes nothing; any other ^ or $ in such a pattern is refused with why, since mvzr would read it as the text's ends. ^ inside an alternation holds only where a search starts, an mvzr limit, documented. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Edit runs sam's command language on a pane's body, as acme's Edit does, in ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | one undo step Over 9P a rename everywhere was a loop of addr and data writes. Edit, from a tag, a pane ctl or exec, parses sam's commands as acme's edit.c does and runs them as ecmd.c does against the text as it was, collecting the changes in order as elog.c logs them and applying them at once: addresses (the addr file's, line:col included), x y g v c a i d s p = m t, u alone, and { }. One undo step; any error, in acme's words, changes nothing, fails a ctl write and is logged. p and = print to the directory's +Errors. Left out, and said: the file commands, the pipes, \1-\9 (mvzr keeps no submatches), and changes out of sequence, which acme applies with a warning. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | addr takes line:col, as Look's file:12:5 doesGabriel Schneider33 hours
| | | | | | | | | | | | A script that knows a line and column had to count bytes to write #n. `12:5` is now the point at line 12, column 5 (bytes from 1, clamped to the line's end and snapped to a character's start, as Look's cursor is), and it composes like any simple address. A pardes extension, documented as one; sam reads it as a syntax error. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The docs say how a --detach=NAME session is posted, what > does to tag, ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | where #n inside a character lands, and what tag click offsets count; a refusal says which ctl takes the word, and a lock refusal who holds it Dogfood round 4's doc list: the recipe assumed pardes/<pid>; the README said tag writes append, though > replaces the editable text; #n inside a multibyte rune or grapheme snaps to its start, unsaid; a tag click's offsets count the path. A word written to the other ctl now says write it to pane/<n>/ctl or /ctl, and a held lock says another open of that ctl holds it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A followed log, event or pty/data answers a read inside its last answer from ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | it again, so bash's read loses nothing bash's read on a seekable fd takes a chunk, keeps one line and lseeks back to just past it; a stream had already moved on, so the rest of the chunk was lost and a while-read loop over the log dropped records. Each stream open keeps its last answer and the offset it was read at, and a read strictly inside it is answered from it; a read at the same offset, as a client that ignores offsets makes, still gets the next record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A shell's > on addr no longer resets it, so echo /re/ > addr searches onGabriel Schneider33 hours
| | | | | | | | | | | | Truncating addr reset it to #0, so a shell's find-and-replace loop matched the first hit for ever, .+#1 read 1 1 each time, and foo x foo y foo became foobarbarbar... acme resets addr on the first open (xfid.c:105-108), for clients that hold the fid; a shell cannot. Here neither an open nor a truncation resets it: the address written is evaluated from the last one, and 0 or , starts over. Documented as a departure from acme. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | get on a pane with unsaved edits refuses once, as acme's doesGabriel Schneider33 hours
| | | | | | | | | | | | A ctl get threw unsaved text away at once. acme's get asks winclean first (exec.c:513): warned once, the same get again discards. A pane dirty only because it was renamed has no text to lose, and is not asked about. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Sixteen 9P connections, and the next one is told there is no room instead of ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | being reset Four slots ran out under scripts plus a mount, and the fifth client was closed without a word, which through a mount looks exactly like a dead session. pardes now serves sixteen, and builds against cloud9 09b77cf, whose runner answers the Tversion of a client it cannot seat with an Rerror "too many connections" and tells pardes, which logs `err - 9p: too many connections`. QUIC keeps its own sixteen and still just closes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A look takes acme's file:addr and :addr, and one that finds nothing changes ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | nothing A look at `file:/re/` or `:/re/` searched for the words instead of addressing, and a miss left an empty +Search pane and a cleared selection, while a hit answered the +Search pane on /look. Now an address after a colon (acme look.c:450) is evaluated in the file from its dot; a miss says no match and leaves the panes and the selection alone; a hit reads back as the pane the text is selected in. Both live in lookAt's one flow, so they are one change. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Undo and Redo are builtins, as in acme's tags, so a pane's ctl and exec can ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | step its body Over 9P there was no way to take back an edit: acme's Undo and Redo were keys only. They are now pane builtins, reached from a tag, a pane ctl and exec, and listed in /commands. They are not added to the default tags, which would change every tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | pardes builds against cloud9 2a7137c, whose 9ns reads a reply that came in ↵Gabriel Schneider33 hours
|/ | | | | | | | before a hang-up 9ns failed every waiting call as soon as one send met a closed socket, so an answer the server sent just before hanging up could be lost: the Restore write's, when pardes cuts its connections. The docs no longer say the Restore write usually fails through a mount; only an older 9ns could, and the log stays the authority. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The docs say which shell a command runs in, what Kill's word matches, where ↵Gabriel Schneider33 hours
| | | | | | | | dumps go and in what time, and how to send code to a REPL Dogfood found the docs saying $SHELL -c where commands run the root ctl's Shell, the README's log line missing run, exit, send, dump and restore, Kill's argument unexplained, and nothing on Repl - and bare Repl, on bracketed paste for multi-line code over pty/data, or on the UTC dump time. The Restore write's ECONNRESET through a mount is documented rather than fixed: pardes sends the answer before the hang-up, and 9ns drops it when its next send fails first. The REPL decision is recorded with the others, and the fs guide says a builtin's word still runs first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Errors are said in words, and a refusal names what it takesGabriel Schneider33 hours
| | | | | | A failure read `Del k|j: InvalidArgument`, `Kill: NoSuchCommand`, `ill-formed control message`, or nothing at all. reportError now spells an error's name as words, and the refusals name their accepted forms: pty/ctl lists its verbs, a flag file takes 1 or 0, a setting word takes on or off, Del takes k, j or nothing, Repl takes - or a language. Kill with nothing to stop says so, /focus says pane, a Look that found nothing says no match, and pty/run on a command pane says it is not a shell. A ctl write's failure has room for the Repl list and is cut between words, the Repl word at a character. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A click written back to event is done as the click, REPL and all; a REPL's ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | ctl line names it Writing an M record back from a .py body with a REPL bound ran the text as a shell command (exit 127), where the click itself went to the REPL. acme does what the click would have done (xfideventwrite, xfid.c:842-844), so a body X record written back now goes the way a middle click goes: to a bound REPL, bracketed or line by line, the several-REPLs question included. An F record, a line written to exec, was never a click and still runs as a command. For a readable list of bindings, the smallest place: a bound terminal's ctl line ends with its id after current/notcurrent. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A REPL takes text only while its program has the terminalGabriel Schneider33 hours
| | | | | | | | | | | | | A binding outlived its program: a command pane reused kept the REPL of the command before, a done command pane could be bound, a document pane (a terminal with no emulator) was accepted, and after Ctrl-D in python3 the text went to the shell, which ran import os as ImageMagick's. A command pane's binding now ends with its command and a done one is refused, a pane with no emulator is refused, and an interactive terminal's REPL is live only while a program other than its shell holds the tty (the host's tty_taken); when none of the language's REPLs is, nothing is sent or run and the pane says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The log's run record carries the whole command line, after the new record of ↵Gabriel Schneider33 hours
| | | | | | | | | | | its pane run logged the line's first word only, and before the new record of the pane it ran in, since panes are announced at the end of a step. It now carries the whole line as msg carries its text (control characters, newlines too, as spaces), and announces the new pane first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The 9P docs find the mount through $NINE_MOUNT, and then the editor is just ↵Gabriel Schneider33 hours
| | | | files
* A terminal bound as a language's REPL takes the execs made on that ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | language's files Repl python in a terminal's tag or on its ctl binds it (Repl - unbinds, Repl bare says the binding, the same word again changes nothing), with an id, python-a, python-b, in its tag. An exec made by a gesture on the body of a file in that language -- a middle click or the execute key, on any text, a single word too -- or on the REPL's own body is typed into it, bracketed if its program asked for that, else line by line with a once-said warning for Python's blank lines, then Enter; the message row says -> python-a in the tag's name tint, the log send <from> <to> <id>. Several bound for the language: the pane asks which on its notice band, as Del asks, one key answering, Esc none, nothing remembered. The gesture is known where it is dispatched (mouse.zig, the execute key), so the tag's words, Exec <text> run by name and a command word @`cmd` stay commands, and a 9P exec is never sent. A finished command pane is no REPL; bindings are not dumped. The docs spell out the escapes, the pdb and input() caveat and the no-bracketed-paste papercut. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command pane's command is over when its process exits, not when its pty closesGabriel Schneider33 hours
| | | | | | | | | | | | | | | | A job left in the background (sleep 100 &) held the pty open, so the pane stayed running and the child a zombie until the job ended; a command that closed its terminal and ran on got its end of file at once, the host waited 100 ms for an exit, reported exit ? and hung it up. Now each command's child is watched on a thread (waitid with WNOWAIT, so its pid stays its own until the host reaps it), and the host tells the core the exit from that: after the pty's end of file, so the output before the exit is in, or 50 ms after the exit without one, a job holding the pty. The pty stays open until both, so a command that let go of its terminal is never hung up by it. All four front ends; a host that cannot start the watcher reads the exit at end of file as before. Tests: host_io's for both cases, and cmdexit.snap end to end. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A reused command pane leaves the last program's screen modes before the next ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | command A program that crashed out of a full screen left the command pane's emulator in the alternate screen with mouse reports, bracketed paste or a hidden cursor on, and the next command ran in that. Before the '% line' separator the pane now leaves the alternate screen, turns those modes off and soft-resets (DECSTR). The docs add that a command which clears the screen and its scrollback erases the pane's history above it. Co-Authored-By: Claude Opus 5.5 <[email protected]>