diff options
Diffstat (limited to 'docs/typ/reference.typ')
| -rw-r--r-- | docs/typ/reference.typ | 156 |
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], |
