From c44894f53decbacc68c0e4e9d1118fc082bc63a0 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 10:02:33 -0300 Subject: A ctl write fails when a builtin it runs fails, and a missing required argument is refused before anything runs A ctl write failed only on a malformed line: Mount x reported its error in the editor while the write succeeded, and a bare Mount failed only as it ran, after earlier lines of the write. acme's ctl answers a command's error (editors/acme/xfid.c:700). Builtins now declare requires_arg beside takes_arg (settings: those with a value to set), and the check refuses a bare one as wrong #args before any line runs; while a ctl runs, the first error a builtin reports fails the write, quoted with its line, and the prompt refusal quotes its line too. Docs say what a failure mid-write leaves done. Co-Authored-By: Claude Opus 5.5 --- docs/fs.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'docs') diff --git a/docs/fs.md b/docs/fs.md index b97f34fa..c08500f1 100644 --- a/docs/fs.md +++ b/docs/fs.md @@ -104,18 +104,28 @@ Config window's, not settings. A pane's `ctl` takes the builtins that act on a pane (`Del`, `Save f`, `Collapse`, `Find pat`) beside acme's `get`, `lock` and `unlock`. The words are case-sensitive and do not alias: acme's verbs are lowercase and the builtins keep their tag spelling, so `Get` is no word -and `del` none either. A write is checked whole before any line runs, and a -line is refused in Plan 9's words for a ctl (kernel/misc/parse.c:82-97): -`unknown control message "X"`, `wrong #args in control message "X"` for an -argument to a builtin that takes none, `bad value in control message "X"` -for a setting's value it does not take, and `not a session control message -"X"` or `not a window control message "X"` for a word of the other ctl; 9ns -maps them all to EINVAL. A builtin that would ask at a prompt for its -argument (`Save` on a scratch, `Find` bare) fails the write with `control -message needs its argument` rather than open one nobody is there to answer, -though a click on the same word written to `exec` still opens it. Like any -write, a ctl write answers once the editor has performed what it asked for -(a save written, a shell started). +and `del` none either. + +A write is checked whole before any line of it runs, and a line is refused +in Plan 9's words for a ctl (kernel/misc/parse.c:82-97), quoting the line: +`unknown control message "X"`; `wrong #args in control message "X"` for an +argument to a builtin that takes none, or none to one that needs it (`Msg`, +`Mount`, `Find`, a setting's value but a switch's, which flips bare); +`bad value in control message "X"` for a setting's value it does not take; +and `not a session control message "X"` or `not a window control message +"X"` for a word of the other ctl. 9ns maps them all to EINVAL, and a write +refused here has done nothing. A line that then fails as it runs fails the +write with the error the editor reports for it and the line, e.g. `Mount: +AlreadyMounted "Mount peer /tmp/s"` (EIO); so does `control message needs +its argument "Save"`, for a builtin that would have asked at a prompt (a +`Save` on a scratch) rather than open one nobody is there to answer. The +lines before a failing one have taken effect and those after it never run, +which is what acme's ctl loop does (editors/acme/xfid.c:600-790). An error +that only happens as the editor performs what a line asked for -- a `Save` +whose disk write fails -- is reported in the editor and /log, not in the +write's answer. Like any write, a ctl write answers once the editor has +performed what it asked for (a save written, a shell started). A click on +the same word, or the word written to `exec`, still opens its prompt. `/commands` lists every builtin the registry holds, in registry order, one a line: its word, `arg` when it takes one, and `root` or `pane` for the ctl -- cgit v1.3