summaryrefslogtreecommitdiff
path: root/.agents
diff options
context:
space:
mode:
Diffstat (limited to '.agents')
-rw-r--r--.agents/skills/pardes-9p/SKILL.md50
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