diff options
Diffstat (limited to '.agents')
| -rw-r--r-- | .agents/skills/pardes-9p/SKILL.md | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/.agents/skills/pardes-9p/SKILL.md b/.agents/skills/pardes-9p/SKILL.md index 9473974c..39a6b1ce 100644 --- a/.agents/skills/pardes-9p/SKILL.md +++ b/.agents/skills/pardes-9p/SKILL.md @@ -40,8 +40,9 @@ the `pid`, `version` and `panes` of a session new enough to serve it. machine. It is not the per-pane kernel mount the `Tty9p` builtin makes, which gives one pane's shell `$PARDES_MOUNT`; see [docs/v9fs.md](../../../docs/v9fs.md) for that. Either mountpoint serves the same tree. A `9ns --unix SOCKET -- cmd` -mount exists only inside `cmd`'s private namespace; to share one, use the -registry (`9ns --mntgen`). +mount exists only inside `cmd`'s private namespace, and there `$NINE_MOUNT` is +the session's own root (`$NINE_MOUNT/index`), not a registry; to share one, +use the registry (`9ns --mntgen`). A running session serves whatever binary started it. If a listing does not match this document, that session predates the change; restart it. @@ -53,7 +54,9 @@ $m/README the served guide, worth reading first $m/index one line per pane: serial, kind (text|term|pdf|image), dirty flag, name $m/status pid, version, panes $m/look write a line = a right click on it at the active pane (file:/re/, file:#n, :/re/ - select by address, as acme's look; a miss changes nothing) + select by address, as acme's look, from the file's dot: file:0/re/ for the + first match; file:N selects the line; a miss changes nothing, logs err, and + look reads back empty) $m/exec write a line = a middle click: an editor command word, or a shell line $m/pane/<n>/pty/run write one line, read `exit N` + its output, or `busy` / `error ...`, on the same open: exec 3<>$m/pane/$n/pty/run; echo make >&3; cat <&3 @@ -142,9 +145,13 @@ but never a 9P write: a script sends code by writing the REPL pane's `pty/data`, and runs a command from such a file with `Exec <text>` or the tag. A bound terminal's `ctl` line ends with its id (`python-a`); an event record written back from such a file's body goes to its REPL, as the click -would. `Repl -` unbinds; a bare `Repl` says the binding. Multi-line code +would. `Repl -` unbinds; a bare `Repl` says the binding. With several +REPLs bound for a language an exec asks which, logged `ask <serial> repl a b` +(Del's side from the keyboard is `ask <serial> del k j`): answer with +`echo 'answer a' > $m/pane/<serial>/ctl`, or `answer -` to send nothing. Multi-line code written to `pty/data` should be a bracketed paste, `\e[200~<code>\e[201~` -then `\r`: sent line by line, a blank line ends a Python block, and Python +then `\r`, and a second `\r` when the code's last line is indented (a `def` +or `for` body): one Enter leaves such a block open. Sent line by line, a blank line ends a Python block, and Python 3.14's REPL auto-indents each line it is typed. Every refused 9P write adds an `err <serial|-> <file>: <why>` record to `$m/log`; through a mount the write itself only says `Invalid argument`. @@ -158,7 +165,21 @@ Rename everywhere, or any sam edit, is one write: `echo 'Edit ,x/foo/c/bar/' v c a i d s p = m t u` and `{ }` (commands in braces one to a line, so from exec or a tag, not a one-line ctl write). Its changes are one undo step, and one that fails changes nothing and fails the write with acme's words (`Edit: -no substitution`), logged as `err`. `p` and `=` print to the directory's +no substitution`), logged as `err`. A block goes in one write to the pane's +`ctl`, the root `ctl` (the active pane) or `exec`: an `Edit` line takes the +lines after it until its `{` closes or its `a`/`c`/`i` text ends with `.`. +bash's builtin `printf` writes line by line, so use a heredoc or `env printf`: + +```sh +cat > $pane/ctl <<'END' +Edit ,x/area_of/{ +i/[/ +a/]/ +} +END +env printf 'Edit ,x/foo/{\ni/</\na/>/\n}\n' > $pane/ctl +``` + `p` and `=` print to the directory's `+Errors`. Not there: `b B D e r w f X Y`, `< | >`, and `\1`-`\9` in `s`. | Operation | Shell | Python client | @@ -175,7 +196,7 @@ inserts after the first: write `addr` again before each replacement. Truncating `data` is pardes's own (acme ignores OTRUNC and always inserts). | Read the selection | `cat $pane/dot` (offsets), `cat $pane/sel` (text) | the same two reads | | Select the addressed range | `cp $pane/addr $pane/dot` | `client.write(pane + '/dot', client.read(pane + '/addr'))` | -| Reload from disk | `echo get > $pane/ctl` | `client.write(pane + '/ctl', b'get\n')` | +| Reload from disk | `echo get > $pane/ctl` (refused once while there are unsaved edits; again discards) | `client.write(pane + '/ctl', b'get\n')` | | Close it | `rmdir $pane` | `client.remove(pane)` | `addr`, `dot` and `limit` each read the pair of offsets they also accept, which @@ -185,7 +206,10 @@ is why copying one onto another is all that acme's `addr=dot`, `dot=addr` and `12:5,14:1`), whose regexps are mvzr's searched as sam searches: `^`/`$` match at any line's start and end, `.` and `[^...]` never match a newline, the leftmost match wins (the first alternative there, not the -longest). An expression is evaluated from the current address (the last one +longest). In a pattern with `\n`, `^` works only first (`^def .*\n` finds +every def line) and `$` only just before a `\n`; anywhere else the pattern is +refused, not silently unmatched. `^` inside an alternation (`^def|^ `) holds +only where the search starts: fine in `x` over lines or `g`, not mid-line. An expression is evaluated from the current address (the last one written, or just past the last `data` write): `.` is that address, not the selection, `/re/` searches on from its end and wraps unless `limit` is set, `?re?` or `-/re/` searches back, `#100,#50` fails `addresses out of order`, @@ -194,8 +218,11 @@ past a step budget (about 300 ms) fails with `regular expression search gave up, ...`. A failed address says why (`no match for regexp`, `address out of range`) and leaves no address: `data` refuses until the next good one, so a missed target is never -written at the old one. Moving `dot` scrolls the pane to it. `limit` bounds a -search and reads empty until set; truncate it to lift it. +written at the old one. Moving `dot` scrolls the pane to it. `limit` bounds +only the end of a forward search, as in acme, and reads empty until set; +truncate it to lift it. In `12:5` the column counts bytes from 1 and clamps +past the end of the line; a line past the end is `address out of range`. +A refused write repeated the same way is one `err` line counted, `(x4)`. `dirty`, `mark` and `scroll` read `0` or `1` and take `0` or `1`: whether the buffer differs from its file, whether a write pushes an undo point, and whether @@ -293,7 +320,8 @@ Only terminal panes have `pty/`. Write keystroke bytes to `pty/data`, not command. For an interactive application, send its actual input bytes; `b'\x03'` is Ctrl-C, and Ctrl-U is `b'\x15'` where that application supports it. These go to the child terminal, not to Pardes key bindings. `pty/ctl` takes `winsize C R`, -`sig INT` and `exec`, one per line. +`sig INT` and `exec`, one per line. `pty/status` reads one line: the pty's cols, +rows and busy (1 while a command runs or text is typed at the prompt). `client.screen()` returns `cols`, `rows`, `cursor`, `styles` and row-major `cells` of `[grapheme, style_index]`. Reconstruct rows using `cols`; resolve |
