summaryrefslogtreecommitdiff
path: root/src/exec.zig
Commit message (Collapse)AuthorAge
* A setting only the other frontend has (Font, GripWidth in a terminal) is ↵Gabriel Schneider22 hours
| | | | | | passed over in the init file, not failed: one init file serves the window and the terminal Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Saving the init file in a pane (Config) applies its settings at once; its ↵Gabriel Schneider23 hours
| | | | | | | | | | | | commands are not run a second time A setting changed in the init file took effect only at the next start. The host's Save now hands a written init file's text back to the core, which applies its setting lines again (each idempotent), with the same notice and err for one that fails; a command line in it (`Newcol`) belongs to the start and is left alone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The init file reads past a UTF-8 BOM, and every line it fails is said and ↵Gabriel Schneider23 hours
| | | | | | | | | | | | logged with its line number, never silent A BOM made the first word unknown, a word no builtin has was skipped without a word, and a setting that refused its value said nothing (the init file ran with announcing off). Each failing line now leaves a notice and an `err - init file line N: <why>` record; `#` still starts a comment only at a line's start, so `#ff0000` stays a value. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A bound REPL whose program exited is skipped, as the docs say: out of the ↵Gabriel Schneider23 hours
| | | | | | | | | | | | question, the running one taking the text, and a done command REPL's tag says no id Two bound REPLs always asked, an exited one offered and, chosen, sent nothing. Now an exited one is left out: one still running takes the text with no question, none running is said (`no program running`), and nothing runs as a command. A command pane bound as a REPL whose command is done no longer shows its id in the tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An exec or Tty from a pane whose directory is a peer's path refuses before ↵Gabriel Schneider23 hours
| | | | | | | | | | | making any pane: `exec: <dir>: no such directory`, no `exit 127` pane left A peer's directory (`/n/peer/x`) is no directory on this host, where the shell starts, so a command there ran in a pane that could only say `(pwd) exit 127`, and a Tty made a new/del pair. missingDir now counts such a path missing, as it does a local directory that is not there. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command or terminal pane refused for room is refused before anything is ↵Gabriel Schneider23 hours
| | | | | | | | | | | | | | | logged or answered of it, and a serial is never handed out twice A command pane with no room logged `new N` and `run N ls`, was answered to its exec, then went with `del N` and no `exit N`; and sync gave N back (`next_serial -= 1`) to the next pane made, so a script holding N found another pane under it. Tty did the same. Both now take a refused placement back at once, before the run is logged or the serial answered (the pane was never announced, so it leaves no record), and fail the write with no room. The decrement is gone: gaps are fine, and a serial once said names one pane for good. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command pane an exec open was answered is leased to it while that open ↵Gabriel Schneider28 hours
| | | | | | | | | | | | | | stays open: another client's command in the same directory gets a pane of its own A finished command pane was the next command's for its directory, from any client, so with four clients scripting one session, one read another's output as its own last run. An open of a look or exec file whose write was answered a pane's serial now holds that pane: reuse passes over it and a new command pane runs the line. The open's own next command may run there again, and once it is closed the directory's one command pane is reused as before. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command run from a pane gets acme's $winid, the serial of the pane it was ↵Gabriel Schneider33 hours
| | | | | | | | | | | | run from; one from a column's or the workspace's tag gets none PARDES_PANE names the command pane itself, so a script a click ran had no way to address the pane it was run in, as acme's win scripts do with $winid. The command pane now remembers that pane and its child gets winid set to it; a header tag's command, which no pane owns, gets winid unset. PARDES_PANE is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* One diff-aware expansion for a click, a 9P whole-line look and an empty ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | event write-back; a blank context line resolves to its path:line The mouse expanded a diff line by its kind (a header or a hunk line's prefix to the line's address, a hunk line's code to words), but an empty look written back to event used the plain word expansion, so ML on a `+` took nothing, and a 9P look of a blank context line (` `) was refused as whitespace. look.diffClick is now the one answer: the mouse, the whole-line look and the event write-back all ask it, and a blank context line is a line like any other. A test asks all three on each kind of line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* With several REPLs bound for a language the pane always asks which, as ↵Gabriel Schneider33 hours
| | | | | | | | | | | | documented, whether or not a program runs in each Only REPLs with a program running were counted, so with two bound and one at its shell prompt the text went to the other without a word, and which REPL got it depended on what happened to be running. All bound REPLs are offered now; one chosen with no program running is sent nothing and says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A shell command from the workspace's or a column's tag runs as a command ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | pane in the session's directory, never typed into the terminal with the keyboard A command clicked in a header tag, or written to /tagexec or a column's exec, was typed into the active terminal when it sat at an empty prompt, so it ran in that pane's directory and left no run or exit record. It now always gets a command pane of its own in the session's directory, as acme's row and column tags have no directory but the session's. tags.md writes the rule down: pane words act on the column's active pane, a column's words on the column, shell commands as their own panes, and over 9P a pane's word is refused. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A diff line looks up the path and line it names, as any look doesGabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | The look on a diff line was its own resolver: a walk up to .git/.jj from the diff's directory, its own "no such file here" and "deleted by this diff". A review tool's cached patch, in no repository, missed every file though the session's terminals sat in the checkout. Now a diff line only expands and transforms. Its expansion (what the hover shows) is the whole line for a header, a `@@` line, or a hunk line pointed at on its prefix, and its text is the look address the line names (look.diffAddress): `path` for `diff --git`/`---`/`+++`, `path:c` for `@@ -a,b +c,d @@`, `path:N` for a hunk line's new line (a removed line's, the new line now where it was). That text goes through the regular look exactly as if selected by hand: same resolution, placement and errors. A 9P look of a whole diff line takes the same transform. Kept: the line classification, hunk arithmetic, git prefix stripping and timestamp cutting (diff.zig). Gone: the repo-root walk, its messages, Target.old_side and deletesAhead, and the click's row stash (Pardes.diff_look). A test compares a B3 on a cached patch's line with a look of the hand-selected `entry/src/entry.rs:2` in the same session. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Every setting's bad-value refusal names what it takes: InactiveDim 0-100, ↵Gabriel Schneider33 hours
| | | | | | | | | | | | MessageLinger 0-60000 milliseconds, a path's limit, a font's form A setting that chooses among words named them, but one that takes a number, a path or a font said only "bad value" over 9P and "does not take that value" from a tag, leaving the range to be guessed. The refusal, both ways, now says its range or what it takes, from one table beside the words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A builtin for one kind of pane is refused on another with why: Petscii, ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | Palette, Ascii, Filter, Togglettymode, the Pdf words, Mode and TreeContext Each of these did nothing, silently, on the wrong kind of pane, so a ctl or exec write of Palette to a text file answered ok as if it had acted. A builtin now declares the one kind it is for (needs), the registry reads it, and runBuiltinFrom refuses the rest before dispatch, as Repl and Edit already refused theirs. Mode and TreeContext, which take more than one kind, say their own refusal. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A right click on a diff line opens the place it names: its file, the hunk's ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | new line, the line itself In a diff pane (a .diff/.patch file, or a command pane's diff output), the look's own expansion, which its hover shows, takes a whole line for a `diff --git`, `---`, `+++` or `@@` line wherever the pointer is on it, markers included, and for a hunk line when the pointer is on its `+`, `-` or space. Then the look opens the file (a/ b/ dropped, timestamps cut) at the line from the hunk header and the lines above it: `@@` the hunk's first new line, context and added lines their own, a removed line the new line now where it was. `diff --git` and `+++` open the new file; `---` the old one, unless the `+++` under it names another. On a hunk line's code the expansion is its words, the prefix never one of them, and looks as ever. Other panes are untouched. Paths resolve in the repository (walking up to `.git` or `.jj` from the diff's directory, or a command pane's), then that directory. A file not here opens nothing and says `Look: b/x: no such file here`, or `deleted by this diff`. A 9P look writing a whole line of the diff does the same. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A diff reads as the code it changes: hunks in their file's language, added ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | and removed rows tinted A .diff or .patch pane, and a command pane whose output is a diff (`git diff`, `git show`, `diff -u`; told by a `diff --git` line, or `---`/`+++` with a `@@` under them, in its first rows), colour each hunk's code in the language of the file its section names (`+++ b/<path>`, `--- a/<path>` for a deleted file), with tree-sitter, as highlightLocations does for results. src/diff.zig walks a unified diff by its `@@` counts, so a removed line that reads `--- x` is no header. Each side of a hunk is parsed as one text (context and removed lines the old side, context and added lines the new), so a string or comment across lines colours as it does in the file; a side no line takes its colours from is not parsed. A section's hunks share a parse, in pieces of about 40 lines (a hunk past 80 is cut), only those in view, and each piece's colours are kept by its bytes, so scrolling back and a terminal's every repaint parse nothing again. Added and removed lines carry a flag in their style byte; the painter tints their rows to the pane's edge, a little way from the page toward the theme's ANSI green or red, and draws the prefix in that hue pushed to read on it. A file in no known language keeps the old line colours. A command pane is read once its command has finished: its rows are copied once (File.DiffOutput, dropped when the pane runs again), so no frame dumps the scrollback, and painted over what git printed. A running command is shown as it prints. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A path typed with a leading ~ is the home directory, at every entry point ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | | | | | | | | | | | | | | that takes one, through one helper Only DumpDir (dump.zig) and ShaderBuild expanded `~/`, each its own way. So a look at `~/notes.txt`, `name ~/x`, `Save ~/x`, ThemeFile, Restore and a quoted `pardes '~/x'` all took `~` as a directory of that name under the pane's. There is now one rule, filesystem.expandHome. A leading `~`, alone or before `/` or `:`, is $HOME, else the passwd entry's home; `~user` is that user's (getpwnam). As in a shell, it applies even beside a file named `~`, and `./~` names that file. Every entry point runs its typed path through it: - look, B3 and 9P, before any parsing, so `~/x:12`, `~/x:12:3` and `~/x:/re/` all work; - name, and a tag's rename; - Save <path>; - ThemeFile, DumpDir, Restore and ShaderBuild's shader files; - the forwarding launch. Recent rows are not shown with `~` and need nothing. How names are shown is unchanged. Tests: expandHome's cases, and HOME unset (passwd), with HOME passed in rather than set, since setenv moves the environ a spawned child reads. fs.py covers Save into missing directories under `~`, `name ~/x`, a look at `~/x:3`, and a forwarded `pardes '~/x'`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* pane/new takes rows from a pane in another column before refusing ENOSPC, as ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | acme's placement does A pane/new whose column had no room was refused "no space for a pane in that column", even with another column holding a tall pane that could give rows. acme takes rows wherever a window has them before saying there are none. pane/new now tries the other columns as +Errors already did: an empty one, else its tallest pane's bottom half, last column first. It is refused only when no pane anywhere can give the rows. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* DumpConfig's lines that set nothing start with #, and a line starting with # ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | runs as nothing at an exec, a ctl or the init file DumpConfig's information lines ("Platform: tty", "Startup config: ...") began with words. Written back, as the report means to be, or clicked, each ran as a shell command or failed as an unknown control message. Each now starts with `# `. A line starting with `#` is a comment, as in a shell: it runs as nothing, silently, at an exec, at the root's, a pane's or a column's ctl, and in the init file. Documented in fs.md and config.md. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* With no pane at all, the root look opens its file and the root exec runs its ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | | | command in the session's directory /look and /exec run at the active pane, and with every pane closed they failed ENOENT, "file does not exist", about a file the writer never named. Now an exec runs as the workspace tag's would, in the session's directory: a builtin at the stand-in, a command in a command pane. An empty window's click now runs a command line too, not only session words. A look runs from a scratch made as New makes one, which also makes the column. That scratch is dropped, unannounced, when the look went to another pane, so opening a file leaves only the file. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* acme's Tab, Indent, Local, Incl and Abort are refused as acme words pardes ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | has not, never run as shell commands The five were missing from the refused list, so at an exec or a ctl a typed `Indent on` fell through to the shell as a command named Indent. pardes has no equivalent for any of them: its tabs and indentation follow the file, commands always run in the pane's directory, and there is no include path or abort. They now get the same "invalid: acme's X is not a pardes builtin" as Zerox or Send. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* New and Tty run at /tagexec and a column's exec, and with no pane at allGabriel Schneider33 hours
| | | | | | | | | | | | | The words New and Tty make a pane in the session's directory, and fs.md already has them run at a tag no pane owns. But /tagexec refused New as a pane's word, since the workspace tag does not hold it. Every header exec also failed ENOENT when no pane was left, and Tty gave up when it had no pane to take a directory from. Now New and Tty are every tag's words. A header exec with no pane runs at the stand-in, as a click in the empty window's tag does, and Tty with no pane asking starts in the session's directory, as New's scratch does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Dumps and init files from before 0.0.4 load no more of their old tag ↵Gabriel Schneider33 hours
| | | | | | | | formats, and three orphan test scripts go A2: a restored pane's tag tail comes from the dump's tag_tail, which every dump since 0.0.4 writes; the 27 earlier default tails that were recognised to upgrade, restoreTail, tailClass, savedPrefix and restoreTailAt, pdf_view's and image's legacySavedPrefix, a terminal's TTY tag prefix and its raw output tail replay, and the ThemeSel, FontSel and ColumnTags words (init lines and dumped output names) go, with their tests; the CHANGELOG says so. A4: test/fs_soak.py, referenced nowhere (monkey9p.py does its work). A6: test/column_grip.py and test/look_placement.py, referenced nowhere; the six review scripts docs/ui-review.md names stay. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Terminal.zig is terminal.zig: a file of functions and no fields takes a ↵Gabriel Schneider33 hours
| | | | | | | | namespace's lowercase name The last of the deferred renames, now that the tty and theme agents have landed: panes.terminal at its importers, the alias lines in Text.zig and File.zig and panes.zig's own uses following. dump.zig's Terminal struct, a dump record, is not this. The served sources list and docs/design.typ name the new file. test/perf.zig's references change, so the three perf baselines take its new harness id with their numbers as recorded. No behaviour changes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Under pardes's placement a pane whose neighbour is in no column goes at a ↵Gabriel Schneider33 hours
| | | | | | | | column's foot, not nowhere After Delcol took the last column's panes, pane/new under Placement made a scratch that no column held, since a scratch was placed only under the asking pane, which was gone; a look from it then unwrapped the missing parent in belowParent and panicked (the 9P monkey's crash-e1873f34). Both now fall back to the foot of the active column, else the last. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* acme's words run as pardes's or are refused, never as shell commands: Put savesGabriel Schneider33 hours
| | | | | | Put, Get, Delete, Snarf, Cut, Paste, Zerox, Sort, Putall, Load, ID and Send written to exec or tagexec each ran as a shell command that exited 127, the write answering 0 -- a Put that looked like a save. Put now runs Save and Delete a Del that does not ask; the rest are refused, EINVAL, invalid: acme's X is not a pardes builtin (with where pardes does it, where it does), in exec and ctl alike. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Delcol on the last column leaves the window, empty but for its workspace ↵Gabriel Schneider33 hours
| | | | | | | | tag, as acme's does The last column's Delcol ended the session. The window now stays, with only the workspace tag; Newcol, and New (which makes the column it goes in), start it again. A word run with no pane at all runs with a stand-in that is no pane, the root ctl takes session words, and pane/new makes its scratch in the session's directory. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A path with a part over 255 bytes is refused, never a panicGabriel Schneider33 hours
| | | | | | std's statFile takes the kernel's ENAMETOOLONG for a bug (errnoBug), so a name, look, DumpDir or Save path with a part over 255 bytes panicked the editor (exec.kindOf via writeName, recentKeeps, dumpFailed). Every non-test statFile now goes through fs.statPath, which refuses such a name as NameTooLong first; fs.py drives long, looping, not-a-directory and not-ours paths through name, look, DumpDir, Dump and Save. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A Theme hint drops whole names to fit, never cutting one mid-wordGabriel Schneider33 hours
| | | | | | The names were written into a fixed room until it ran out, the last one cut, and the click's form ran past the 128 bytes a 9P error carries. Each name now goes in whole or not at all, and both forms are sized to fit. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A builtin or setting this build lacks is refused GUI-only, from an exec tooGabriel Schneider33 hours
| | | | | | On a terminal, Fonts written to an exec was no builtin there, so it ran as a shell command and ended exit 127; ctl said unknown control message. Both now say Fonts is GUI-only, invalid here (a builtin another platform's build has, not in this build). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Theme takes a name in any case, and a miss names its nearest themesGabriel Schneider33 hours
| | | | | | Names were case-sensitive, and a miss listed only the first letter's themes that fitted 40 bytes, 4 of the many d ones. It now lists every theme sharing the first letter when they fit the 128 bytes an Rerror carries, else the nearest by a plain likeness score (shared prefix, the name inside, its letters in order). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A Dump into a DumpDir that is no directory says so; the doc says a missing ↵Gabriel Schneider33 hours
| | | | | | | | last directory is made DumpDir /dev/null said no such directory though it is there, and the doc claimed a missing DumpDir always fails, where its last component is made at the Dump. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Recent keeps only files on disk, and its cap never drops an open oneGabriel Schneider33 hours
| | | | | | A renamed scratch never saved and a /virtual/ pane were recorded as recent files, and at 200 the oldest entry went even when that file was open. Opens, renames and closes now record a path only when it is a file on this host, and the cap drops the oldest closed entry. A name with a newline is not written to the kept list, where it would read back as two. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A list pane opened from a terminal that has not said its directory yet lands ↵Gabriel Schneider33 hours
| | | | | | | | in the session's ThemeSel (Themes) in an init file ran at a terminal whose shell had not reported its cwd, so +Themes opened as /+Themes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The panes present at boot are the log's first records, before what an init ↵Gabriel Schneider33 hours
| | | | | | | | file said The boot announce ran after the init file, so its msg (ThemeSel: renamed to Themes) came before new 1. A msg or path record said while the log is still empty now announces the panes first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A builtin's Verbose announcement is the message row's alone, never loggedGabriel Schneider33 hours
| | | | | | With Verbose on by default, /log filled with msg - DumpDir, msg 4 Grep and the like, with machinery to take an announcement back out when its builtin failed or said something itself. A msg record is now only something said; the take-back machinery goes with it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* ThemeSel is Themes and FontSel is Fonts; the old words still work in init ↵Gabriel Schneider33 hours
| | | | | | | | | | | | files and dumps The user asked for the plainer words. Every use is renamed: the builtins, leader paths, /commands, the docs and tutor, tests, and the themesel golden, re-recorded. An init file's ThemeSel or FontSel runs the new word and says `ThemeSel: renamed to Themes`, as ColumnTags is said; a dump naming an output pane by the old word restores it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A column takes panes until their minimums fill it, not until none can be halvedGabriel Schneider33 hours
| | | | | | | | | | Placement halved the tallest pane or refused, so 11 panes filled 48 rows that hold 16 at their tag and two rows each: the refusal did not match the documented arithmetic. When no pane can be halved but the minimums with the new pane's fit, the column's rows are shared out again; and a refused pane's removal leaves no pane under its minimum. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command from a missing directory fails ENOENT with no pane; one whose ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | shell never started ends exit 127 Exec made a command pane in a directory that was not there, whose shell never started: it said running for ever, a follower waited for an exit that never came, and Kill found it. The line now fails up front, as Tty does, `exec: <dir>: no such directory`; and a command pane whose shell the host could not start ends `exit 127` at once. A shell that could not start in its directory says `directory missing`, not `file not found`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A terminal is typed into only when idle at an empty promptGabriel Schneider33 hours
| | | | | | | | | A look at a directory, or an exec at a terminal, typed its line after whatever sat unsent at the prompt and ran the two joined (`echo TYPEDls`). A terminal with text at its prompt now takes no line; a look at its directory opens a new terminal, an exec runs as a command pane. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Tty in a missing directory fails and makes no pane; a shell that never ↵Gabriel Schneider33 hours
| | | | | | | | | | | | | started answers runs The host could not start the shell (its chdir failed), and the pane stayed with no pty: a run written to it waited for a prompt for ever. Tty now refuses a directory that is not there, `Tty: <dir>: no such directory`, before making a pane; and a terminal whose shell the host could not start (Pardes.shellFailed, from each host's spawn) answers any run with `error shell gone`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A Save whose write fails changes nothing: not the name, not the dirty flagGabriel Schneider33 hours
| | | | | | | | | A scratch took its new name before the host wrote it, so `Save /root/x.txt` failing with EACCES renamed it anyway; a failed write to another name marked a clean file dirty. A scratch is now named once its write is done (promoteSaved), and a failed write puts the saved revision back. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An event record never carries flag 2, as no expansion record follows; flag 1 ↵Gabriel Schneider33 hours
| | | | | | | | | | | | reads the first word In acme flag 2 promises a second record with the expanded range, and acme's libraries read one. F records set it always and a click with no range known set it, with none following: a library then took the next event for it. Records here carry the word already, so 2 is never set. Flag 1 now reads the first word as acme's lookup does, so `Msg hi` is 1. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A builtin's Verbose announcement is logged only when it succeedsGabriel Schneider33 hours
| | | | | | | | | | | A failure said while it ran (Exit's refusal, a Del refused) or later by the host (a Save's write, a Dump's) left `msg N Save` in the log as if it had worked. The announcement's record is remembered and taken back out on either, unless a follower read it already. A refused pane/new logs its err alone, and a failed Dump says its reason in words (`file not found`, not `FileNotFound`) so its msg goes and the err is the one record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Tty takes a directory as long as a path may beGabriel Schneider33 hours
| | | | | | | | | | | A terminal's directory rode inline in the spawn effect, capped at 256 bytes, so Tty in a directory of about 377 bytes said path too long. A directory past the inline buffer now goes out of line (Pardes.spawn_dirs, given to the host when the spawn is performed), up to the host's path limit (4095); past that, Tty says its directory is longer than a path may be. The effect queue stays its size. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A chorded exec an event reader holds is told its argument, and runs with itGabriel Schneider33 hours
| | | | | | | | | | | | With event open, a 2-1 chord's exec went out as one record with flag 8 and nothing after it: the argument was freed unsaid. As acme does (exec.c:150-190), two records follow it, the argument's text and where it came from (file:#q0,#q1, empty when not known), and the pane keeps the argument, so the record written back runs with it (acme's own write-back, xfid.c:842, passes none; the reader was told, so it runs as the click would have). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A bare Shell names the shell it goes back to, and 12:0 says columns count from 1Gabriel Schneider33 hours
| | | | | | | | | A bare Shell reset to the default without saying which; it now says Shell: the default again, <shell> ($SHELL, else /bin/sh). A line:col of column 0 said only address out of range; it now adds that a column counts from 1. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A file changed on disk never reloads over unsaved editsGabriel Schneider33 hours
| | | | | | | | | | | | | | | A watched file rewritten on disk was loaded over a buffer's unsaved edits and its dirty flag cleared, so Exit and Del no longer asked about them. A clean buffer still reloads; one with edits keeps its text and stays dirty, says <file> changed on disk (get reloads it, Save overwrites it), logs changed <serial>, and its Save warns once before overwriting the newer file, as acme's Put refuses a file modified since read (exec.c:577); get asks as ever (winclean, exec.c:513). The restored-watch test's dirty case now keeps the snapshot, and the filewatch snapshot script (re-recorded by name) checks both halves: the edited pane keeps its edit and says so, the clean one reloads. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A multi-line paste into Python's REPL runs whole, back at its promptGabriel Schneider33 hours
| | | | | | | | | | | | The Enter went on Python's first output after the paste, before it had taken in the whole paste, and one Enter leaves a multi-line input at ... anyway. Python's output now only restarts a 100 ms quiet wait (the 250 ms fallback stays), and a paste of more than one line gets the second Enter a block gets. fs.py runs print(11)\nprint(22), the same with a trailing newline, and a for block followed by a statement in a real python3, each back at >>>. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A command run from a column's tag gets its pane in that columnGabriel Schneider33 hours
| | | | | | | | | A command from a column's tag ran in a command pane at the foot of the last column, however far from the tag, and could reuse a finished one anywhere. It now goes to the tag's column, under both placements, and reuses only a finished command pane in that column. Co-Authored-By: Claude Opus 5.5 <[email protected]>