summaryrefslogtreecommitdiff
path: root/docs/typ/scripting.typ
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 23:53:38 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:18 -0300
commitbe7fb126aefedee221d0d32109acb9fc4b71d474 (patch)
treef080f205f1fa47f183d6781a2901dd48e5d4536a /docs/typ/scripting.typ
parent244704dabbe279d03f1432f8474e985aeb25f2ad (diff)
downloadpardes-be7fb126aefedee221d0d32109acb9fc4b71d474.tar.gz
pardes-be7fb126aefedee221d0d32109acb9fc4b71d474.zip
The docs take the 9P agent's round 30: log stats 0, names escape every control byte, $winid and the pager defaults, the one client rule, and Shift-Esc said one way in the guide and the cheatsheet
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'docs/typ/scripting.typ')
-rw-r--r--docs/typ/scripting.typ71
1 files changed, 26 insertions, 45 deletions
diff --git a/docs/typ/scripting.typ b/docs/typ/scripting.typ
index a00ee612..8b5831b8 100644
--- a/docs/typ/scripting.typ
+++ b/docs/typ/scripting.typ
@@ -18,32 +18,30 @@ Each session listens on a Unix socket,
(the editor's pid), `PARDES_9P` (the socket) and `PARDES_PANE` (their
pane's serial).
-Two clients do the rest. `9ns` comes from cloud9
-(`git.sr.ht/~gbrls/cloud9`; its `zig build` installs `9ns` on Linux) and
-mounts a 9P tree through FUSE in a private namespace, no root needed;
-`9p` is plan9port's, and reads and writes without a mount.
+Pane shells and command panes alike can reach the session; one rule picks
+the client:
-#cmd("9ns --mntgen # every posted session, under $NINE_MOUNT")
-#cmd("9ns --unix \"$PARDES_9P\" -- sh -c 'cat \"$NINE_MOUNT/index\"' # one session, for that command")
-#cmd("9p -a \"unix!$PARDES_9P\" read index # no mount")
+- *With a mount* (`$NINE_MOUNT` set, as under cloud9's `9ns --mntgen`;
+ `git.sr.ht/~gbrls/cloud9`, whose `zig build` installs `9ns` on Linux),
+ the session is a directory and plain `cat` and `echo >` work:
+ #cmd("s=${PARDES_9P##*/pardes-9p-}; m=$NINE_MOUNT/pardes/${s%.sock}\ncat \"$m/index\"")
+ (Under `9ns --unix SOCK -- cmd` the session is `$NINE_MOUNT` itself.)
+- *Without one*, plan9port's `9p` talks to the socket:
+ #cmd("9p -a \"unix!$PARDES_9P\" read index\necho Save | 9p -a \"unix!$PARDES_9P\" write pane/3/ctl")
-Under `9ns --mntgen` find this pane's session from its socket:
+The recipes below use `$m`; with `9p`, `cat $m/x` is `9p ... read x` and
+`echo y > $m/x` is `echo y | 9p ... write x`. A dead session's registry
+entry stays listed and answers `Input/output error`: name the session,
+never glob. A running session serves the binary that started it. The
+reference has the other ways in: a #word("Tty9p") terminal's kernel mount,
+and the Python client in the source tree.
-#cmd("[ -n \"$NINE_MOUNT\" ] || echo 'no 9P mount: use 9p or the Python client'")
-#cmd("s=${PARDES_9P##*/pardes-9p-}; m=$NINE_MOUNT/pardes/${s%.sock}")
-#cmd("cat \"$m/index\"")
-
-Under `9ns --unix` the session is `$NINE_MOUNT` itself (`m=$NINE_MOUNT`),
-and in a #word("Tty9p") terminal (#key("SPC n 9")) it is `$PARDES_MOUNT`.
-A dead session's registry entry stays listed and answers `Input/output error`: name the session, never glob. A running session serves the binary
-that started it.
-
-#word("Tty9p") opens a terminal with the session kernel-mounted (Linux
-v9fs): it asks for your sudo password in the pane, mounts the socket in a
-private mount namespace and starts your shell as you, with
-`PARDES_MOUNT` set. Only that shell sees the mount, and each takes one of
-the session's 16 connections. It needs the `9p` and `9pnet_fd` kernel
-modules and the `pardes-v9fs` helper the build installs beside `pardes`.
+A command run from a pane (#btn("B2") on a line in its tag or text) also
+gets `$winid`, the serial of that pane, as acme's commands do; it is unset
+for one run from a column's or the workspace's tag, and `PARDES_PANE`
+stays the command pane's own. Every pane's child, a terminal's shell or a
+command, gets `PAGER=cat` and `GIT_PAGER=cat` unless your environment sets
+them, so nothing waits in a pager.
= Recipes
@@ -62,6 +60,7 @@ The paths below are under `$m`; `p=$m/pane/$n` for a pane.
[run at a prompt], [#cmd("t=$(awk '$2==\"term\"{print $1; exit}' $m/index)\nexec 3<>$m/pane/$t/pty/run; echo ls >&3; cat <&3; exec 3<&-")],
[type, interrupt], [#cmd("printf 'q' > $m/pane/$t/pty/data # \\r Enter, \\x03 Ctrl-C\necho 'sig INT' > $m/pane/$t/pty/ctl")],
[ask the language server], [#cmd("echo /myFunc/ > $p/addr; echo dot=addr > $p/ctl\necho Hover > $p/exec # also Rename new, Symbols")],
+ [act on the pane a command came from], [#cmd("#!/bin/sh\n# fmt-here: put its name in a pane's tag, click it with B2\nn=$winid; f=$(cat $m/pane/$n/name)\necho Save > $m/pane/$n/ctl && zig fmt \"$f\" && echo get > $m/pane/$n/ctl")],
[follow what happens], [#cmd("exec 3<>$m/log; echo 'follow new' >&3\ntimeout 30 cat <&3; exec 3<&-")],
)
@@ -103,6 +102,10 @@ pardes the editor of every program run there.
the bad one fails. Send a block as one write (`cat block > $p/ctl`), and
end every write whose result matters with a newline.
- plan9port's `9p write` opens with OTRUNC: `echo x | 9p write pane/3/body` replaces the whole body. Append with `>>` through a mount.
+- #file("pty/run") runs in the terminal's own shell, so a command that
+ pages waits in the pager when your environment names one (pardes sets
+ `PAGER` and `GIT_PAGER` to `cat` only when it does not): run
+ `git --no-pager ...` or `PAGER=cat ...`.
- `tail -f log` never sees anything new: write `follow` on the open you
read. Through a FUSE mount bash's `read -t` cannot time out: wrap the
loop in `timeout`.
@@ -120,28 +123,6 @@ pardes the editor of every program run there.
- A #word("Restore") hangs up every connection: dial again and restart the
mount.
-= No mount: the Python client
-
-`test/ninep.py` in the source tree speaks 9P itself, for when nothing is
-mounted or a fid must stay open (#file("event"), #file("pty/data"), a
-followed #file("log")). Its paths are the served root:
-
-```python
-import sys
-from ninep import Client # PYTHONPATH=test
-with Client(sys.argv[1]) as c: # a socket path, or (ip, port)
- print(c.read('/index').decode(), end='')
- n = int(c.read('/pane/new'))
- c.write(f'/pane/{n}/body', b'hello\n', truncate=True)
- fid = c.open(f'/pane/{n}/event', 0) # hold event: clicks come here
- c.write(f'/pane/{n}/exec', b'Msg hi\n')
- print(c.read_fid(fid, 0, 4096)) # b'FX0 0 1 6 Msg hi\n'
- c.close(fid)
- c.remove(f'/pane/{n}')
-```
-
-`client.screen()` returns the parsed #file("/screen").
-
= An isolated session
Never experiment on a session someone is using. Strip every `PARDES_*`