summaryrefslogtreecommitdiff
path: root/docs
Commit message (Collapse)AuthorAge
...
| * | Alt-( and Alt-) rotate the text of the selectionsGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | [<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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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]>
| * | Every helix-golf example is a differential case, one per step of its walkthroughGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The ten examples on helix-golf are imported as 118 cases: each numbered step of an example's walkthrough is the case whose keys are the command up to and including that step, so the first mismatch names the step where pardes and helix part. Six more restart at a step that begins with %, from helix's own text there, so a later step is tested even when an earlier one misses. zig build hxgolf compares all 124 with goldens from hx-harness. 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
|/ / | | | | | | files
* | A terminal bound as a language's REPL takes the execs made on that ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | 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 terminal's Tty word names its shell, Tty+fish, and a click on it opens anotherGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | /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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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]>
* | docs: the log's restore record, not the Restore write's answer, says a ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | Restore happened The answer gets 200 ms to leave before the connections are cut, so a slow client may see only the cut; the new log's 'restore <path>' record is what to trust. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | docs: what dogfooding asked of the second roundGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 Schneider3 days
|/ | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | '<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 Schneider3 days
| | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | 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 Schneider3 days
| | | | | | | | | 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 Schneider3 days
| | | | | | | | | | | | | 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 Schneider3 days
| | | | Co-Authored-By: Claude Opus 5.5 <[email protected]>