summaryrefslogtreecommitdiff
path: root/docs/typ/reference.typ
diff options
context:
space:
mode:
Diffstat (limited to 'docs/typ/reference.typ')
-rw-r--r--docs/typ/reference.typ156
1 files changed, 127 insertions, 29 deletions
diff --git a/docs/typ/reference.typ b/docs/typ/reference.typ
index a7f2c869..14243384 100644
--- a/docs/typ/reference.typ
+++ b/docs/typ/reference.typ
@@ -17,7 +17,7 @@ one-screen summary of this page.
/README the one-screen summary (src/fs-help.txt)
/index a line per pane: serial kind dirty name column
/status pid, version, panes
-/look /exec write a line: a right / middle click at the active pane; read: the serials touched
+/look /exec write a line: a right / middle click at the pane with the keyboard; read: the serials touched
/pager write a directory: its one +Pager, made or emptied; read: its serial
/log the event log; write `follow` to wait for more
/screen the rendered screen as JSON
@@ -224,7 +224,10 @@ A line written to #file("exec") is a #btn("B2") click:
ranges it changed (on the message row, and so in the log) without listing
them, and fails when there is nothing to rename. One that reaches other
files applies nothing: it opens a `+Search` preview of the edits, which
- is the pane the write answers, and says how many it lists;
+ is the pane the write answers, and says how many it lists. So does one
+ the server answers in this file alone while another open file of its
+ language still holds the old name, a row per such file (zls renaming at
+ a declaration; from a use it reaches every file);
#word("Diagnostics") and #word("Symbols") list the file's in `+Search`;
#word("Lspinfo") fills `+Lsp`, the pane its write answers, with which
server serves the file and its state (`not started yet` until its first
@@ -237,7 +240,7 @@ A line written to #file("exec") is a #btn("B2") click:
`Snarf`, `Cut`, `Paste`, `Zerox`, `Sort`, `Load`, `ID`, `Send`, `Tab`,
`Indent`, `Local`, `Incl`, `Abort`) are refused, `invalid: acme's Get is not a pardes builtin: ...`, never run as commands. So is a GUI-only
builtin (`Fonts`) on another frontend.
-- Anything else is a command line, at most 1024 bytes, run as the guide
+- Anything else is a command line (a typo ends `exit 127`), at most 1024 bytes, run as the guide
says (#doc("tags", section: "command-panes")): typed into a terminal idle
at an empty prompt, else run in a command pane. #file("exec") reads back
the command pane's serial, and while that open stays open the pane is its
@@ -249,7 +252,7 @@ reused pane's #file("body") keeps every earlier run
#cmd("awk '/^% /{out=\"\"; next} /^exit [0-9?]+/{next} {out = out $0 \"\\n\"} END {printf \"%s\", out}' body")
From a pane whose directory is gone nothing runs: `exec: <dir>: no such directory` (ENOENT).
-The root's #file("look") and #file("exec") act at the active pane and log as
+The root's #file("look") and #file("exec") act at the pane with the keyboard and log as
that pane's (with no pane at all, in the session's directory: a look opens
its file, making a column as #word("New") does, and an exec runs its
command there); #file("/pane/<n>/look") and #file("exec") at pane n;
@@ -312,7 +315,7 @@ Writes take settings and session builtins (`scope = .session` in
- #word("Exit") quits. While panes hold unsaved text it refuses once
(#doc("tags", section: "unsaved-panes")): one `unsaved <serial> <name>`
record per pane, then the write fails `<name>: Modified (Exit again to discard)` or `4 unsaved panes: Modified (Exit again to discard)` (EIO),
- and the list stays in a `+Unsaved` pane (in the active pane's directory,
+ and the list stays in a `+Unsaved` pane (in the directory of the pane with the keyboard,
or the session's when that directory is not on disk). #word("Restore"), #word("Del"),
#word("Delcol") and a pane's `get` refuse the same way with their own
word, except that #word("Delcol") opens no `+Unsaved` pane: it names the
@@ -358,15 +361,16 @@ word clicked in a tag does. The same lines go in the startup file
(#doc("config")).
#pairs(
- [`Theme <name>`], [`orchard`; names as #word("Themes") lists them, #word("NextColor") walks the ring (#doc("themes"))],
+ [`Theme <name>`], [`orchard`; names as #word("Themes") lists them, #word("NextColor") steps to the next in that list (#doc("themes"))],
[`ThemeFile <path>`], [a `.zon` theme, relative to the config directory; reloads live when saved],
[`FocusTint`], [on: tint the focused pane's and column's tags],
[`SyntaxBold`], [off: bold syntax keywords],
[`Verbose`], [on: a builtin announces its name on the message row],
[`MessageAnimation`], [on: messages ease in and dissolve],
[`MessageLinger`, `MessageFall`, `MessageDissolve`], [800, 180, 150 milliseconds, at most 60000],
+ [`PagerColor`], [on: the next paged text keeps its colours],
[`Pager pardes|off`], [`pardes`: what a terminal's commands page through, `pardes -`; `off` leaves `PAGER`, `GIT_PAGER` and `SYSTEMD_PAGER` as the environment has them (#doc("fs", section: "pardes-stdin")). It applies to terminals started after it],
- [`Placement acme|pardes`], [`acme`: where new panes go (#doc("tags", section: "new-panes"))],
+ [`Placement acme|pardes`], [`acme`: where new panes go (#doc("fs", section: "placement"))],
[`BootShell keep|replace`], [`keep`; `replace` closes the untouched lone shell a dragged document lands beside],
[`LookWord search|list`], [`search`: a looked-at word selects its next place, or lists all in `+Search`],
[`TermImages real|petscii`], [`real`: a new terminal draws its program's kitty graphics (yazi's previews) as pixels where the shell can; #word("Petscii") flips one terminal; a tty under a terminal without kitty graphics draws them as glyph art either way],
@@ -426,7 +430,7 @@ Resting the pointer on text for about 32 ms (`look_preview_delay_frames`,
#file("/layout") has a line per column, left to right: `serial index x width current|notcurrent empty|full pane-serials...`, then `active <serial>` (the active column: where #file("pane/new") and a look put the
next pane; `-` when none). `current` is the column with the keyboard now,
-which may differ from the active one (#doc("tags", section: "active-column")).
+which may differ from the active one (#doc("tags", section: "command-panes")).
#file("/index")'s last field is each pane's column serial.
A session holds 16 columns (`no space for a column: 16 max`, ENOSPC), each
@@ -470,7 +474,7 @@ ordinary edit and #key("u") in the tag undoes it.
`<dir>/+New` (the session's directory), and reading that open answers its
serial: `n=$(cat $m/pane/new)`. *Each open makes another pane*; two reads
of one open answer the same serial. It goes where a #word("New") from a
-tag would (#doc("tags", section: "new-panes")): in the active column,
+tag would (#doc("fs", section: "placement")): in the active column,
filling it if empty, else the bottom half of its last pane. A session
holds 64 panes (`no space for a pane: 64 max`), and every pane keeps its
tag and 2 rows (`no space for a pane in that column: each keeps its tag and 2 rows`); both are ENOSPC, for this open and for a look, exec,
@@ -536,7 +540,9 @@ redo available, then `current`/`notcurrent`, a REPL's id if bound,
tint:disabled|filtered|full`. It
takes:
-- the pane builtins: #word("Del") (`Del k`/`Del j`, or
+- the pane builtins: #word("Del") (from the keyboard between two panes it
+ asks which takes the rows; a click, a ctl write or an `init` line never
+ asks and gives them to the pane above; `Del k`/`Del j`, or
#word("DelAbove")/#word("DelBelow"), give its rows to the pane above or
below), `Save [path]` (making the directories the file goes in first,
whichever name it writes), #word("Collapse"), #word("Undo")/#word("Redo")
@@ -549,7 +555,7 @@ takes:
- `lock`/`unlock` (acme's). The lock binds only clients that take it and
belongs to the open that wrote it: `exec 3>$pane/ctl; echo lock >&3; ...; exec 3>&-`. A `lock` another open holds fails at once, `file in use`
(EBUSY): retry.
-- `answer <choice>` to the question the pane asks on its notice band,
+- `answer <choice>` to the question the pane asks on its message row,
logged `ask <serial> <what> <choices>` (`ask 4 del k j`, `ask 4 repl a b`, `ask 4 save path`); `answer -` takes it back.
- acme's lowercase ctl words, done by what replaces each: `name x`, `put`
(Save), `clean`/`dirty`, `del`, `delete` (no asking), `dot=addr`,
@@ -642,7 +648,7 @@ ceiling:
== Edit <edit>
`Edit <sam commands>` on a pane's #file("ctl") or #file("exec") (or the
-root's, at the active pane) runs acme's Edit on the body: addresses as
+root's, at the pane with the keyboard) runs acme's Edit on the body: addresses as
above, commands `x y g v c a i d s p = m t u` and `{ }`. All changes are
one undo step, applied only if every command succeeds; a failure changes
nothing and fails the write with acme's words (`Edit: no substitution`).
@@ -767,7 +773,7 @@ A program holding the terminal (a REPL, `less`) takes no run: write to
One 64 KiB ring, one record a line, kept whether or not anyone reads it.
An open freezes it and reads to EOF. Write `follow` to that open to then
wait for each new record (`follow new` skips the history, as `tail -n0 -f`); `tail -f` never writes `follow`, so it sees nothing new. A follower
-the ring outran reads `lost N` first. A Restore hangs the follower up: dial
+the 64 KiB ring outran (it keeps only the newest records) reads `lost N` first. A Restore hangs the follower up: dial
again and read from `restore <path>`. A follower's read held when the
Restore comes takes every queued record that fits first, so records written
just before the Restore are not lost.
@@ -786,7 +792,7 @@ just before the Restore are not lost.
[`restored <old> <new>`, `restoredcol <old> <new>`], [serial maps after a Restore],
)
-The serial is the pane the line ran at (the active pane for the root's
+The serial is the pane the line ran at (the pane with the keyboard for the root's
#file("look")/#file("exec")), `-` for the root #file("ctl"),
#file("/tagexec") and column files. A record said again straight after
itself is counted, `err 3 addr: no match for regexp (x4)`; a follower sees
@@ -810,9 +816,9 @@ at 200, ending in `…`. Control characters become spaces.
- #file("/pager"): write a directory, `~` expanded and resolved (an empty
line is the session's; one not there is refused ENOENT, a relative one
EINVAL, one you may not write `permission denied`, a regular file `not
- a directory`, ENOTDIR); a read on
- the same open answers the serial of that directory's one `+Pager`, made
- or emptied for it. It takes one directory a write. This is what
+ a directory`, ENOTDIR), one line; then, on the same open, the text to
+ page, escapes and all. A read of that open answers the serial of the
+ directory's one `+Pager`, made or emptied for it, once the text is in. This is what
`pardes -` uses; from a directory you may not write, it pages into the
session's `+Pager`.
- #file("/listeners"): the session's dial addresses, a line each
@@ -825,20 +831,103 @@ at 200, ending in `…`. Control characters become spaces.
`-Dembed-sources=true`; `EffectCode <effect>` lists an effect's files
under `/virtual`.
+= The pardes command <command-line>
+
+In a pane's shell (`PARDES_PID`, `PARDES_9P` and `PARDES_PANE` set),
+`pardes FILE` writes FILE to that pane's #file("look") and returns at once;
+a FILE not there yet opens an empty pane that #word("Save") creates, making
+its directories. What the session refuses (a bad name; a name under a
+directory you may not search or write, `permission denied`) is printed and
+the exit is 1. `--` ends the options (`pardes -- -name`).
+`pardes --wait FILE` (`-w`) returns 0 when the pane showing FILE is
+deleted, 1 when the session goes away or no longer answers; with
+`PARDES_9P` set but no pane of its own it opens FILE in that session and
+waits there. Bare `pardes` in a pane refuses and names `--nested`, which
+starts a separate session whose shells do not forward to it.
+
+= Placement <placement>
+
+`Placement acme` (the default) puts a new pane in the column whose tag
+asked, else the active column (last typed or #btn("B1")-clicked in,
+dropped into, its tag given the keyboard, or given the last new pane),
+never a new column. An empty column it takes whole; #word("New") and
+#file("pane/new") take the bottom half of the column's last pane; a pane
+opened from a pane's text (a look, #word("Tty"), #key("Alt-n")) goes under
+the pane with the most blank rows, or halves the biggest. #word("New") in a
+pane's tag names its `+New` in that pane's directory and column; from a
+column tag, in that column and the session's directory. A command pane
+goes to the last column, or the column whose tag ran it, under either
+placement. `Placement pardes` fills an empty column whose tag asked or has
+the keyboard, puts a scratch or a shell under the pane that asked, and a
+document beside the last one read (or in a column of its own on a wide
+screen). No pane is made shorter than its tag and two rows; with no room
+the pane is refused.
+
+A command pane runs in the directory it started in, whatever its command
+does with `cd`, and relative looks in it resolve there. The next command
+for that directory reuses a finished one (from a column tag, only one in
+that column); one still running, one a background job still prints to, or
+one a #file("exec") open still holds is never reused.
+
+= Find and Grep <find-grep>
+
+Find matches file names, Grep the text of lines, both literally and
+ignoring ASCII case. Grep reads at most 256 KiB of a file and stops at 512
+hits, Find at 512 names. The walk stops at 20000 files or 100000 entries,
+16 deep, and passes over `.git`, `.jj`, `target`, `node_modules`,
+`.venv`, `__pycache__`, `.zig-cache` and `zig-out`. A cap hit, or a
+directory it could not open, is said at the end: `cut at 512 hits`, `N
+files read only in part (first 256 KiB)`, `walk cut at N entries`, `N
+directories skipped: permission denied`. A search that finds nothing and
+skipped nothing fails, `Grep: text not found`, and leaves the `+Search` as
+it was.
+
+= On screen <on-screen>
+
+- *Esc at a prompt.* pardes knows a shell prompt with nothing typed on it
+ from the OSC 133 marks it injects into bash and fish (marks a shell sends
+ itself do not count); for other shells, from no program holding the
+ terminal, typed text or not.
+- *A program's mouse.* A program that tracks the mouse (htop, vim with
+ `mouse=a`) gets #btn("B1")'s clicks and drags and the wheel over its
+ grid; Shift-#btn("B1") selects and Shift-wheel scrolls pardes's
+ scrollback, while Shift-#btn("B2") and Shift-#btn("B3") go to the program.
+ A full-screen program that does not track the mouse gets the wheel as
+ arrow keys. Tags, grips and gutters stay pardes's.
+- *Diffs.* A `---` line opens the old file unless the `+++` under it names
+ another; a removed line's `-` goes to the line now standing where it was.
+ git's `a/` `b/` (and `c/ i/ w/ o/`) prefixes are dropped; a
+ `--no-prefix` diff's paths are kept.
+- *Sessions.* Bare `--detach` names the session after its pid; bare
+ `--attach` needs exactly one session; a second `--detach=NAME` while NAME
+ runs says so and exits 1. Frontends share the smallest common size. With
+ none attached, `size C R` sets the screen, messages clear by the clock,
+ and a pty reports its size in pixels at the last frontend's cell size
+ (8×16 before any), as CSI 14, 16 and 18 t do.
+- *Config.* The startup file is `$XDG_CONFIG_HOME/pardes/init` when that is
+ absolute, else `~/.config/pardes/init` (macOS:
+ `~/Library/Application Support/pardes/init`); a line that fails is
+ skipped, and text that is no builtin is not run. A dump keeps panes,
+ columns, tags, selections, the theme and changed settings; a terminal
+ comes back with its last MiB of output and a new shell in its old
+ directory; undo history and REPL bindings are not kept. A crash appends
+ two lines (build, time, platform, pid; the panic message) to `crashes`
+ beside `init`.
+
= pardes - <pardes-stdin>
`pardes -` reads stdin to its end and shows it in the directory's one
-`+Pager` pane, made or emptied for it and left clean; the next paged text
-refills it. Terminal escapes go (colour, hyperlinks, a man page's
-overstrike), a carriage return keeps a progress line's last state, CRLF
-becomes LF, and NUL, BEL, SO and SI are dropped. Empty stdin shows
-nothing. Inside a pardes pane it returns at once; a text the session cannot
+`+Pager` pane, made or emptied for it and left clean, opening at its top;
+the next paged text refills it. The session parses the text with
+ghostty-vt: SGR colours become the `+Pager`'s own display, never part of
+its body or any read (`PagerColor off` pages plain), and every other
+escape is dropped; a carriage return keeps a progress line's last state,
+and CRLF becomes LF. Empty stdin shows nothing. Inside a pardes pane it returns at once; a text the session cannot
take is printed to stderr with why, and the exit is 1. From a directory
whose name holds a newline or control byte, the pane is the session
directory's. Outside a pardes pane it starts a new editor whose first pane
-the text is. It writes stdin through one open of the body, so any size up
-to a file's limit (256 MiB) arrives whole; past that it is cut, with a note
-saying so.
+the text is. Stdin up to a file's limit (256 MiB) arrives whole; past that
+it is cut, with a note saying so.
With `Pager pardes`, a terminal's shell gets `PAGER`, `GIT_PAGER` and
`SYSTEMD_PAGER` set to this pardes plus ` -` (the path quoted only when it
@@ -848,8 +937,17 @@ first, then `PAGER`; your own `MANPAGER` wins.
= Other ways in <other-clients>
-The scripting chapter's rule (a mount, else plan9port's `9p`) covers most
-uses. Two more:
+A session listens on `$XDG_RUNTIME_DIR/pardes-9p-<name>.sock` (else under
+`~/.local/state/pardes`), `<name>` the pid, the `--detach=NAME` or
+`--9p=NAME`, and posts it in the 9P registry as
+`$XDG_RUNTIME_DIR/9p/pardes/<name>`. Its pane shells get `PARDES_PID`,
+`PARDES_9P` and `PARDES_PANE`. A dead session's registry entry stays
+listed and answers `Input/output error`: name the session, never glob.
+Under `9ns --unix SOCK -- cmd` the session is `$NINE_MOUNT` itself.
+plan9port's `9p write` opens with OTRUNC, so it replaces a whole
+#file("body"); append with `>>` through a mount. Through a FUSE mount
+bash's `read -t` cannot time out: wrap a follow loop in `timeout`. The
+scripting chapter's rule (a mount, else `9p`) covers most uses. Two more:
- #word("Tty9p") (#key("SPC n 9")) opens a terminal with the session
kernel-mounted (Linux v9fs): it asks for your sudo password in the pane,
@@ -881,8 +979,8 @@ with Client(sys.argv[1]) as c: # a socket path, or (ip, port)
= Limits <limits>
#pairs(
- [panes], [64 (16 on the board)],
- [columns], [16 (6 on the board), each at least 10 cells wide],
+ [panes], [64],
+ [columns], [16, each at least 10 cells wide],
[rows a pane keeps], [its tag and 2],
[msize], [65536 (64 KiB) offered],
[connections], [16 Unix and TCP, 16 QUIC],