summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAge
...
| * | Backspace in a line's leading blanks goes back to the previous indent stopGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | helix's delete_char_backward dedents: when everything before the cursor on its line is blank, it deletes back to the previous multiple of the indent width, a whole unit when already on one (a tab before the cursor still goes alone). pardes deleted one space, so O<backspace> under an indented line left three of four, which is where helix-golf's function_into_class ended up. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | Alt-( and Alt-) rotate the text of the selectionsGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | helix-golf swaps keys and values with rotate_selection_contents (webS_to_ <ret><A-(>, then per line). Each range's text moves to the next range (the previous one for Alt-(), in one edit; a count rotates by that many ranges, each range comes back over the text it now holds in its own direction, and the primary follows its text. That is the harness's helix; 25.07.1 read the count as a group size and left the primary alone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | Alt-J joins lines and selects the spaces it put inGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | helix-golf's text_into_array turns lines into an array with %<A-s>ms"<A-J>i,: join_selections_space joins like J and leaves one cursor on each space it inserted. J and Alt-J now make one edit over every range, as helix does, rather than J being replayed per range; that is what lets Alt-J hand back all the spaces as the new selection. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | Blank lines open above a selection's first line and below its lastGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | [<space> and ]<space> measured from the cursor's line, so over a selection of several lines whose head was at the bottom, [<space> opened a line INSIDE the selection. helix takes the range's line_range: above its start, below its end. helix-golf's export_from_mod (yp[<space>) is where it showed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | Replacing a selection with the register keeps its directionGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | R always left the head on the pasted text's last char. helix maps the replaced range through the change, so a backward selection comes back backward, its head on the first char: helix-golf's reverse_golf_example (xbR) is where it showed. SPC R shares the path. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | Surround keeps the direction of the selection it wrapsGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | ms<ch> always left the wrapped range pointing forward. helix gives each range back with_direction(range.direction()), so a selection made backward (b, or v moving up) keeps its head on the open, which is where the next motion starts from. helix-golf's csv_to_sql (bms`) is where it showed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | The board build compiles again: pty status and run read no prompt marks ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | where there are no terminals pty.zig reached into a terminal's stream handler, which is void on esp32p4, so the board build stopped at readStatus and writeRun. Both now know at comptime that such a build has no marks. 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 Schneider30 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]>
* | | A REPL question's answer goes to the pane its letter offered, or says that ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | one is gone The letter was looked up again when answered, so a REPL closed or rebound while the question stood could hand the text to another pane with the same letter, or drop it without a word. The question now keeps each letter's serial; the answer is that pane, still bound and running, or a message. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Errors are said in words, and a refusal names what it takesGabriel Schneider30 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 REPL's language is named and found as the syntax table finds one: aliases, ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | any case Repl took only the grammar's exact name, and a file's language was found by a case-sensitive suffix of its path, apart from the aliases a code fence already had. The aliases move to grammar_manifest with byName and byPath, which syntax, Repl and langOf share, so `Repl py` and a .PY file work. The line-by-line warning is for the python language, not an id that starts with python. Joincol's doc line was sitting on Repl. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Focus on a closed pane goes to the pane that takes its place, never to the ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | one focused before Dogfood closed a pane in one column and focus jumped to another column, only because that pane was focused last. Now removePane decides for every route (Del, a ctl del, a command pane's end, a 9P remove, a stillborn scratch replaced): the pane that grew into the rows, or the scratch standing in an emptied column; removeColumn gives it to the pane level with it in the column that takes the width. Closing an unfocused pane leaves focus alone. The per-caller focus lines in Del and replaceStillborn are gone, and so is prevFocus. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A build that runs no commands refuses a word that is not a builtin, and says soGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | Board and web have no spawn. An unknown word there used to fall through to the command path and do nothing visible; now it answers with a failure the caller sees. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | The web and board builds compile again: a shell's lookup and a dump's read ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | are the host's The Tty shell check sized a buffer with std.fs.max_path_bytes and the Restore check read the dump through the host filesystem, both in the core, which the wasm32-freestanding build cannot compile (no PATH_MAX, no libc). Both now run only where there is a host, as the rest of that code does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Text sent to a REPL is plain lines, sent whole or not at allGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A CRLF became two line ends, the blank line ending a Python block; an ESC in the text, ESC[201~ above all, could end a bracketed paste early; and on the board, whose writes are 128 effects of 64 bytes with nothing pending, a send past 8 KB was cut and lost its closing ESC[201~ and Enter, leaving the REPL in a paste. Lines now end in LF alone, ESC and every control byte but tab and newline are dropped, and a send larger than can be written at once (Pardes.writeRoom) is refused with a message instead of cut. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A command's exit is told once its output is in, by the pty's state, not a timerGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The watcher woke the host a second time 60 ms after the exit by its own clock while the grace was counted from the reap: a host busy for 10 ms missed it, and the tag said running for ever and Kill did nothing; and under load exit 0 could land before the last output. As decided, no timer: the exit is told once it is reaped and the pty says nothing is left (poll: no POLLIN, and no POLLHUP, which means the end of file is on its way behind the output), else at that end of file, checked after each chunk of output. The tty host checks inside its step so the frame shows it. The four hosts' copies are one host_io.takeExits/commandEof, which close a told command's pty at its end of file (the fd and the GUI's reader leaked when the exit came first). A finished command pane whose pty a job it left still holds is not reused, so that job is not hung up; and the reset before a reuse is SGR 0, not DECSTR, which ghostty's stream does not implement. 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 Schneider30 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]>
* | | Whether an exec came from a body travels with it, so every selection goes to ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | the REPL The execute key and the middle click marked a global flag that the first execute cleared, so of several selections executed at once only the first reached a bound REPL and the rest ran as commands. Where an exec came from now goes with it, as acme's execute() asks of its Text (exec.c:122,169): builtins.Ctx carries from_body, runBuiltinFrom and executeFrom take it, the gestures set it, and chordEachSel sets it for each selection. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A detached session stopped by SIGTERM, SIGINT or SIGHUP unlinks its socketsGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The signals' default action ended the process where it stood, leaving pardes-9p-*.sock and pardes-detached-*.sock for the next session to trip on. The detached session now takes them to mean quit: the handler sets a flag and wakes the loop, which leaves as Exit does, through the teardown that unlinks both. fs.py sends each of the three and checks the sockets are gone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A 9P request that fills a stillborn scratch's column replaces the scratch ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | before it is answered A pane that joins a column holding only an empty +New takes the column, but that replacement ran at the end of the editor's next update, not of a 9P request: a look answered 19 while index still listed the +New 18, whose del came later. serveFs, a step of its own, now runs it too before answering. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A restored terminal's tag names neither the REPL it was nor the shell it hadGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dump keeps a terminal's whole tag, and restoring read its tail from it after the directory: the REPL id and Tty+fish, which were live facts and not the tag's text, came back as a custom tail, so the tags said python-a over a fresh shell bound to nothing. Restoring now sees through the id and the shell in the Tty word, a default tail stays the default, and the new shell names itself when it starts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A REPL takes text only while its program has the terminalGabriel Schneider30 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]>
* | | Tty with a shell that is not there says so, and never sets the caller's shellGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Tty /nonexistent or Tty fsh started the host's fallback shell without a word, and when spawnTty made no pane, the argument became the calling pane's shell. Tty now looks the shell up first and fails 'Tty: no shell "fsh"' when it is neither a name on the usual paths nor a path to one; spawnTty answers the pane it made, the one given the shell, and says why when it made none. The lookup (host_io Shell.find) gives the turn up around its access() calls, since a typed path may be under a mount this editor serves, and forkShell copies the pane's shell before looking it up and checks the pane is still its own after. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A Restore of a dump that cannot be read fails at once, and spends no warningGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The dump was read only by the host after the step, where a failure went to the message row alone: a Restore written to ctl answered success, logged no err, and a second one past the unsaved-text warning did the same. Restore now reads the dump first, before the warning, and says 'Restore: <path>: no such file' (or permission denied, a directory), which fails a ctl write and so logs err. A bare Restore with no dump yet, or a name too long, says so too. 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 Schneider30 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]>
* | | A command pane echoes its first command as it does the later onesGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | Only a reused pane showed '% line' above its command, so the first command's output stood with nothing saying what made it. Every command is echoed now, the first too. The goldens of chordcut, cmdexit, cmdword and layout-open gain that line and the rows below it move down one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A command of several lines keeps its pane's tag to one row, and the tag ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | never panics on a longer prefix A two-line exec made a command pane whose tag prefix held the line's newline, so the tag ran to a second row and tagTintRange sliced its first row past its end: panic. acme runs a multi-line selection as one command, and so does pardes; the tag now shows the line's first row, cut at a character's start, and '...', tagTintRange stays inside the row it is given, and the '% line' echo turns the line's newlines into the terminal's, so it does not staircase. 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 Schneider30 hours
|/ / | | | | | | files
* | A terminal bound as a language's REPL takes the execs made on that ↵Gabriel Schneider30 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]>
* | Kill signals a command only while it runs, and only the pane it was meant forGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | A signal effect carried only a slot, so a Kill followed in the same step by the pane's closing and its slot's reuse signalled the new pane's child; and a command pane whose child had exited and been reaped kept a process group id another process could take. The effect now carries the pane's serial, checked as it is performed, and a host signals no command whose exit it has recorded; the core already sends Kill only to a command it has not been told is done. 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 Schneider30 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 Schneider30 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]>
* | Only Tty reads Word+arg as its argumentGabriel Schneider30 hours
| | | | | | | | | | | | | | | | Every builtin that takes an argument split a word at its first +, so Dump+2024.zon ran Dump with 2024.zon. A builtin now opts in with plus_arg, read by the registry, and only Tty does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A spawn names the pane it was made for, so a pane closed and its slot ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | retaken spawns nothing The spawn effect carried only a slot, and the host read the command and shell off whatever pane held the slot as it forked: a command pane closed and its slot taken by the next one before the effects ran forked the new pane's command twice. The effect now carries the pane's serial and is dropped when the slot holds another; forkShell checks it again after giving up the turn for its directory's stat, the one moment a 9P client can change the panes under it. Every front end performs spawns with the turn, from its step. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A terminal's Tty word names its shell, Tty+fish, and a click on it opens anotherGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A terminal's tag said Tty whatever shell it ran. The host's acknowledgement of the shell it forked now sets the word to Tty+<shell>, tinted like the tag's name. Word+arg is taken as Word arg, one word a tag can hold and a click can take whole (+ is a word character), so Tty+fish opens a terminal on fish, as Tty fish does; Tty takes the shell as its argument, which the host forks for that pane instead of the configured one. Every snapshot whose screen shows a terminal's tag changes: 69 goldens, re-recorded by name, whose 297 changed lines are all Tty becoming Tty+bash (the harness runs bash), the cursor columns and style spans that moved with it, or that text cut at a pane's width. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A command line runs as its own command pane unless it is clicked at a ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | shell's prompt A middle click, an exec write or a tag word that no builtin knows was typed into some terminal for the pane's directory, sharing whatever state that shell was in and answering nothing, so a misspelling vanished into a shell. Now only a line clicked at an interactive terminal's prompt is typed there. From anywhere else it runs as a command pane: a terminal whose child is $SHELL -c the line in the pane's directory, full emulation, which shows its output and then exit N from the host's reaping of the child, and stays. A finished command pane is the next command's for its directory, which runs below what it showed after a '% line' line (acme appends to +Errors and never clears it, util.c:213); a running one gets a second pane. Kill ends a command pane's whole process group, the log records run and exit, exec reads back the command pane's serial, and a line is at most 1 KB, read off the pane as the host forks rather than carried in every spawn effect. ttyForDir's search for a free shell is gone. The goldens of chordcut, cmdword and layout-open change where a file's exec now opens a command pane, and ttytaken is rewritten to exec from the terminal itself; docs/open-questions.md records the decision. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Unattended messages expire in the detached session's loop, not as a 9P ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | request is served serveFs expired them, but a read is answered while a step is out in a syscall, because reads change nothing, and this one changed pane messages and needs_frame from under the step. The detached session's loop now expires them between steps, and while nobody is attached and a message is up it looks again every 100 ms rather than waiting for something to wake it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Addresses: acme's ; is tested and documentedGabriel Schneider30 hours
| | | | | | | | | | | | | | | | /a/;/b/ searches b from the end of a (acme's addr.c:170-171 sets ar to the left side), and /a/,/b/ searches both from the current address; the review asked that it be confirmed, and it held. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The root exec is a click at the keyboard's pane, and goes to its event ↵Gabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | reader too A line written to the root's look or exec is a click at the pane with the keyboard, and in acme every click on a window whose event file is open goes to its reader; the root's acted at once. It now goes to the reader as the pane's own does. The docs say what that means for a helper holding event (its own exec comes back as a record: run it through ctl, or write the record back), and why an event record counts bytes where acme counts runes: every offset pardes serves is in bytes, #n and q0/q1 too, so the count follows them rather than switch alone, and an acme library reads it right for ASCII text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A Restore tells old connections from new by when they were acceptedGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | | | | | The Restore marked the connections to cut in cloud9's Conn.user, which cloud9 also writes, clearing it for a connection accepted into that slot on another task: a client dialling in as the marks were made could be marked old and cut. Each connection is now stamped from a counter as it opens (cloud9's opened hook), and a Restore cuts those stamped before its own count; nothing is written from two tasks. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A Restore's warning about unsaved text no longer lets the next Exit discard itGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | Exit and Restore shared one warned-at revision, so a Restore a script was refused over ctl spent the warning, and the person's next Exit quit without asking, throwing the text away. The warning now records which word gave it, and only that word goes ahead on it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | docs: what dogfooding asked of the second roundGabriel Schneider30 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 Schneider30 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 Schneider30 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 Schneider30 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 Schneider30 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]>
* | A terminal's body stats as long as it readsGabriel Schneider30 hours
| | | | | | | | | | | | | | | | | | stat said a terminal's body was 0 bytes while a read gave its screen and history, and the docs promise real sizes; a client that sizes its read from stat got nothing. The length is now that of the text a read answers, counted the way the pane's ctl line already counts it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | An address searches back after a minus, and a range ending before its start ↵Gabriel Schneider30 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 Schneider30 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 Schneider30 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]>