summaryrefslogtreecommitdiff
path: root/.agents
diff options
context:
space:
mode:
Diffstat (limited to '.agents')
-rw-r--r--.agents/skills/pardes-9p/SKILL.md34
1 files changed, 24 insertions, 10 deletions
diff --git a/.agents/skills/pardes-9p/SKILL.md b/.agents/skills/pardes-9p/SKILL.md
index 16e90dc9..1d32ce7a 100644
--- a/.agents/skills/pardes-9p/SKILL.md
+++ b/.agents/skills/pardes-9p/SKILL.md
@@ -34,6 +34,10 @@ cat "$m/pane/$PARDES_PANE/body"
From there the editor is files: `cat`, `echo >`, `ls` and shell scripts are
the whole interface, and nothing below needs more than they do.
+`pardes FILE` run in a pane opens FILE in that session and returns at once;
+`pardes --wait FILE` returns when that pane is deleted (1 if the session goes
+away), which is what `EDITOR='pardes --wait'` needs (`GIT_EDITOR` follows it).
+
Entries for dead sessions stay listed and answer `Input/output error` on any
access, so name the session you mean rather than globbing or taking the newest.
`cat "$m/index"` is the cheapest liveness check, and `cat "$m/status"` reports
@@ -164,9 +168,10 @@ an open that never wrote, the session's last. With other clients about,
write and read one open (`exec 3<>$m/look; echo x >&3; cat <&3; exec 3<&-`).
A read is a stream: once read, a second read on the same fd gives EOF (on
an open that wrote, until its next write); open again, or seek to 0, to read
-it again. Each command line runs once whole, however a mount cuts a big write; a last
-line with no newline runs when the open closes, and an Edit block still open
-then fails there (an `err`: ``unmatched `{'``, or an a/c/i text with no `.`
+it again. Each command line runs once whole, however a mount cuts a big write; a
+write's last line with no newline runs with it (and fails it), unless the
+write filled its 9P message and may go on; an Edit block still open when the
+file closes fails there (an `err`: ``unmatched `{'``, or an a/c/i text with no `.`
line), changing nothing. One rule: a builtin that fails, whether through a
ctl (a pane's pty/ctl `exec` too), look, exec, tagexec or a column's exec,
fails the write (EINVAL for a malformed line, ENOENT for what is not there --
@@ -209,7 +214,11 @@ leaves a multi-line input at `...`). A middle click, or an event
write-back, sends what it needs by itself. 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`.
+`Invalid argument`. Only writes log one: a refused open or truncation
+(an OTRUNC open, as `data`'s after a failed `addr`), create or remove is
+its error alone, as are a write to `pane/new` (`permission denied`) and a
+write on a fid opened read-only (`bad use of fid`). Errors are words, never
+a C errno string. A look miss quotes what was written: `no match for "zzq:#3"`.
## Edit through addresses, dot and the flag files
@@ -274,6 +283,8 @@ A `+New` scratch counts as unsaved (and holds up Exit, Restore, Del) only
once it holds 100 bytes or more. A read
of `data` or `xdata` moves `addr` past what it read, as in acme.
Truncating `data` is pardes's own (acme ignores OTRUNC and always inserts).
+plan9port's `9p write` always opens with OTRUNC, so `… | 9p write pane/body`
+replaces the whole body: append with `>>` through a mount instead.
| 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` (refused once while there are unsaved edits; again discards) | `client.write(pane + '/ctl', b'get\n')` |
@@ -290,13 +301,15 @@ newline, the leftmost match wins (the first alternative there, not the
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. `^def|^ ` finds lines starting either way
-(every branch anchored; a mix like `^def|x` is refused). An expression is evaluated from the current address (the last one
+(every branch anchored; a mix like `^def|x` is refused). `[éa-z]` and
+`[à-ÿ]` match those runes (a range up to 256 runes); `[^é]` and a wider
+range are refused. 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`,
-and a search that backtracks
-past a step budget (about 300 ms) fails with `regular expression search
-gave up, ...`. A failed address says
+and one search that runs past its step budget (about 300 ms; each search of
+an Edit `x` has its own) fails with `regular expression search took too
+much time, gave up`. A failed address says
why (`no match for regexp`, `address out of range`) and leaves no address:
`addr` reads empty and `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
@@ -318,8 +331,9 @@ an open nor a `>` resets it (acme resets it on the first open): each `echo /re/
Write `0` to start from the top. The search wraps, so stop a find-all loop when
the address comes back to where it began, or set `limit`.
`$pane/ctl` reads acme's window status line — serial, tag length, body length,
-a reserved zero, the dirty flag, the width in cells, the font and the tab
-width, then `current` or `notcurrent` — and takes `get` (reload from disk),
+isdir (0), the dirty flag, the width in cells, the font, the tab width, the
+undo flag and the redo flag, as acme's fields — then `current` or
+`notcurrent` — and takes `get` (reload from disk),
`lock`/`unlock`, and any builtin that acts on a pane (`Del`, `Save f`,
`Collapse`, `Undo`/`Redo`: 256 steps; with none left they say so, and the
write succeeds). A `lock` another open holds fails at once with `file in use`