summaryrefslogtreecommitdiff
path: root/docs/fs.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/fs.md')
-rw-r--r--docs/fs.md122
1 files changed, 91 insertions, 31 deletions
diff --git a/docs/fs.md b/docs/fs.md
index 45b04675..d2f35505 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -92,7 +92,7 @@ Existing Plan9port/v9fs clients need a userspace bridge for QUIC.
```
/README this guide, also src/fs-help.txt
-/index one line per pane: serial, kind (text|term|pdf|image), dirty flag, name
+/index one line per pane: serial, kind (text|term|pdf|image), dirty flag, name, column serial
/status pid, version and pane count
/look write a line: a right click on it at the active pane; read: the serials the last
look, exec or ctl write touched (made, else acted at)
@@ -102,16 +102,44 @@ Existing Plan9port/v9fs clients need a userspace bridge for QUIC.
write follow to that open to wait for more
/screen rendered screen JSON; frozen per open handle
/listeners the session's dial addresses
-/focus the serial of the pane with the keyboard; write a serial to give it the keyboard
+/focus the serial of the pane with the keyboard; write a serial to give it the keyboard,
+ which makes its column the active one as a click there would
/ctl the settings, one a line as a write takes them; write a setting or a session builtin
-/commands every builtin: word, `arg` if it takes one, and `root` or `pane`, the ctl that takes it
-/pane/new open it to make a pane; the read answers that pane's serial
+/commands every builtin: word, `arg` if it takes one, `root` or `pane` (the ctl that takes it), a setting's values
+/layout one line per column, left to right: serial index x width current|notcurrent
+ empty|full pane-serials...; then active <serial>: the active column, where
+ pane/new and a look place a pane next (- when there is none)
+/tag the workspace tag; > replaces it, >> appends, one line
+/col/<n>/tag the tag of the column with serial n, the same way
+/col/<n>/ctl write Delcol, Joincol, New or Tty: each acts on that column, as from its tag
+/col/<n>/exec write a word: a middle click on it in that column's tag; rmdir col/<n> closes
+ an empty column (a column with panes is refused, ENOTEMPTY)
+/pane/new open it to make a pane; the read answers that pane's serial. A session holds
+ 64 panes (16 on the board); at that, every route that would open one -- this
+ open, look, exec, New, Tty -- fails with `no pane slots: 64 max` and an err
+ record, and look reads back empty
/pane/<n>/ name body tag ctl addr dot limit data xdata sel dirty mark scroll
errors event look exec, plus pty/{ctl,status,data} on terminals
/os/ the host filesystem
/src/ the editor's embedded sources, only when built with -Dembed-sources=true
```
+`/layout`, `/tag` and `/col` go past acme, which serves no column files --
+its columns are only where a window sits. They are here so a script can see
+where the panes are (`/index`'s last word is each one's column serial) and
+edit the tags a person clicks in: a column tag is one line, a newline
+written into it a space, and a truncating write (`echo Make > col/3/tag`)
+clears it and drops the newline that ends it, as a pane tag's does. A
+column is named by its serial, as a pane is: it stays while the column
+lives, whatever opens or closes beside it, and is never reused; /layout
+gives each column's serial and its index left to right, and the log says
+`newcol <serial>` and `delcol <serial>` as columns come and go, and after a
+Restore `restoredcol <old> <new>` for each column as `restored` does for
+panes. Joincol folds a column into the one on its right, which keeps its own
+serial and tag; the joined one's serial is gone (`delcol`). The root ctl
+takes no column word: its `Delcol` is refused, pointing at
+`col/<serial>/ctl`.
+
Control messages are split by what they act on, as acme keeps window verbs
on a window's ctl and webfs and upas/fs keep session settings on a root ctl.
Each builtin declares its scope in src/builtins.zig (`scope = .session`;
@@ -119,9 +147,11 @@ every setting is one, the rest act on a pane). `/ctl` takes the session's
builtins, one a line, at whichever pane has the keyboard as each runs --
`Newcol`, `Dump`, `Mount name dial`, `Theme ink`, `Verbose off`; `Exit`,
which quits the editor as acme's does (it refuses once, naming each pane with
-unsaved text, `<name>: Modified (Exit again to discard)`, and a second
-`Exit` with nothing edited since quits, throwing that text away; a scratch
-under 100 bytes is not asked about; `Restore`, which replaces every pane,
+unsaved text, a `+New` scratch of 100 bytes or more too, in one line,
+`<name>, <name>: Modified (Exit again to discard)`, and a second `Exit`
+with nothing edited since quits, throwing that text away; a scratch or a
+command's output under 100 bytes is not asked about, as acme's winclean
+asks about no small unnamed window; `Restore`, which replaces every pane,
asks the same first -- `Dump` writes `pardes-<date>-<time>.zon` (UTC) in
`DumpDir` (default `$XDG_DATA_HOME/pardes`, else `~/.local/share/pardes`)
and logs `dump <path>`, and `Restore` with no path takes the last one; a
@@ -151,14 +181,18 @@ in a shell running without job control (`set +m`) the job shares the
shell's group, so there is none to signal: Kill says `Kill: no job to
signal`, and a write of it to `ctl` fails with that; with nothing running
it says `Kill: nothing running`; and, of a typed line, only the
-foreground job, so of `sleep 30; echo done` typed at a prompt the `echo`
-still runs once the `sleep` is stopped --
+foreground job, after which what the rest of the line does is the shell's
+affair: of `sleep 30; echo done` typed at a prompt, fish goes on and runs
+the `echo`, and bash abandons the line, as each does when a job it waits
+on is killed --
and reads every setting there is, one a line, in the words a write of it
-takes (`Verbose on`, `WindowOpacity 70`, `PanelSlide off`, `DumpDir` bare
-for the default directory, `LocationsConfig ...`), so writing what it reads
-back changes nothing; platform and startup facts are `/status`'s and the
+takes (`Verbose on`, `WindowOpacity 70`, `PanelSlide off`, `DumpDir
+<the directory in effect>`, `LocationsConfig ...`), so writing what it reads
+back changes nothing; a setting the frontend cannot show (`Lift`,
+`GripWidth` on a terminal) is refused as `Lift is GUI-only`; platform and startup facts are `/status`'s and the
Config window's, not settings. A pane's `ctl` takes the builtins that act on
-a pane (`Del`, `Save f`, `Collapse`, which folds that pane, `Undo` and
+a pane (`Del`, or `Del k`/`Del j` to give its rows to the pane above or
+below, `Save f`, `Collapse`, which folds that pane, `Undo` and
`Redo`, which step its body through its edits, `Find pat`)
beside acme's `get`, `lock` and `unlock`. The column words are pane words
too, acting on the column that pane is in: `Delcol`, `DelAbove`, `DelBelow`
@@ -193,8 +227,13 @@ performed what it asked for (a save written, a shell started). A click on
the same word, or the word written to `exec`, still opens its prompt.
`/commands` lists every builtin the registry holds, in registry order, one
-a line: its word, `arg` when it takes one, and `root` or `pane` for the ctl
-that takes it, e.g. `Newcol root`, `Save arg pane`, `Verbose arg root`. It is
+a line: its word, `arg` when it takes one, `root` or `pane` for the ctl
+that takes it, and for a setting that chooses among words those words,
+comma-joined, e.g. `Newcol root`, `Save arg pane`, `Verbose arg root on,off`,
+`Placement arg root acme,pardes`. Such a setting written bare steps to its
+next value, so a two-valued one flips (`Crt`, `Placement`, `BootShell`), as
+its word clicked in a tag does; a value it does not take is refused with
+`bad value in control message; takes ...` naming those it does. It is
generated from the registry, so it is always this build's own list.
`/focus` reads the serial of the pane with the keyboard, and a serial written
@@ -307,13 +346,17 @@ terminal's while a program other than its shell holds the tty -- after
Ctrl-D the shell would run the text, so nothing is sent and the pane says
so. Still commands, whatever is bound: a word in a tag (so
the tag is how to run `make` from that file), `Exec <text>` run by name
-(typed, a 2-1 chord onto `Exec`, a `ctl` line) and a command word @`cmd` in
+(typed, a 2-1 chord onto `Exec`, a `ctl` line) -- in a `.py` pane bound to
+a REPL, `Exec print(1)` runs `print(1)` as a command, never in the REPL --
+and a command word @`cmd` in
the text, looked at or clicked (`# @`pytest -x`` in a script). A 9P `exec`
is no gesture and is never sent: a script writes to the REPL pane's
-`pty/data`, multi-line code as a bracketed paste (`\e[200~<code>\e[201~`
-then `\r`, and a second `\r` when its last line is indented: one Enter
-leaves a block open, pasted or typed; a middle click sends that second one
-itself), since line by line a blank line ends a Python block and Python
+`pty/data`, multi-line code as a bracketed paste (`\e[200~<code>\e[201~`,
+then `\r` in a write of its own once the REPL has echoed the paste --
+Python 3.13's REPL takes an Enter read with the paste as part of it, even a
+one-line one -- and a second `\r` when its last line is indented: one Enter
+leaves a block open, pasted or typed; a middle click does all of this
+itself, holding the Enter until the REPL answers the paste), since line by line a blank line ends a Python block and Python
3.14's REPL auto-indents each line typed into it. The REPL gets the text
wherever it is -- at a `pdb` or `input()` prompt too. Bindings are not dumped, so a Restore leaves none.
@@ -344,7 +387,11 @@ selection, and leaves `look` reading back empty.
`/pane/<n>/name` reads the pane's file name (a terminal's directory) and
writing it renames the buffer; a relative name resolves against the pane's
-directory. `body` appends on write and replaces on truncating open. `sel`
+directory. `body` appends on write and replaces on truncating open. A
+terminal's `body` is its history as plain text, frozen per open, in logical
+lines: a row the terminal wrapped is joined back to the row before it (the
+wrap is ghostty's, as `pty/run`'s output unwraps), and the last line ends
+with a newline. `sel`
reads the selected text and writing it replaces the selection. `errors`
appends to the directory's `+Errors` pane. Holding `event` open redirects the
pane's Look and Exec clicks to that client, and so does a line written to the
@@ -372,7 +419,9 @@ for the question the pane asks on its notice band, which the log names as
`ask <serial> <what> <choices>` -- `ask 4 del k j` for Del's side from the
keyboard (`k` the pane above takes the rows, `j` the one below), `ask 4
repl a b` for which bound REPL takes an exec (a REPL's letter) -- `answer -`
-taking it back as Esc does (with no question standing, `answer` is refused),
+taking it back as Esc does (a choice the question does not offer is refused,
+naming those it does, and the question stands; with no question standing,
+`answer` is refused),
and acme's `lock` and `unlock` (editors/acme/xfid.c:603-611), for an
edit of several writes to `addr` and `data` that another client must not
land in the middle of. As in acme the lock binds only the clients that take
@@ -496,9 +545,13 @@ then the text you may edit. A write appends to that text,
newlines included, and a tag with more than one line takes a row per line on
screen; truncating `tag` clears it, as acme's `cleartag` does -- the default
words (`Del`, `Put` and the rest) with it, since they are that text until
-you edit it, so `echo Make > tag` leaves only `Make`; append with `>>` to
-keep them, with `printf ' Make' >> tag`: `echo` ends its word with a
-newline, which starts a new line of the tag. The clearing is an edit of the tag like a typed one and its undo
+you edit it, so `echo Make > tag` leaves only `Make` -- a truncating write
+drops the one newline that ends what it wrote, which would draw an empty
+row, and keeps any other; append with `>>` to
+keep them, with `printf ' Make' >> tag`. The leading blank is needed: the
+tag reads back with no blank after its last word, so `printf Make >> tag`
+glues `Make` onto it; and `echo ' Make' >> tag` ends with a newline, which
+starts a new line of the tag. The clearing is an edit of the tag like a typed one and its undo
history is kept: `u` in the tag brings back the text it cleared, words
included.
@@ -515,16 +568,21 @@ entries carry no sizes, and neither does `/screen`, which has no length until
an open renders its frame; stat the entry.
`/log` is one ring (64 KiB) that records whether or not anyone reads it:
-`new`, `del`, `rename` (a terminal's too, as its shell changes directory,
+`new`, `del`, `rename` (a terminal's too, as its shell changes directory --
+a new terminal is `new N /` until its shell says where it is, then renamed;
+it runs `ls` once at its first prompt, a greeting that shows the directory --
since a terminal is named by its directory), `exit <serial> <N>` before
the `del` of a terminal whose shell exited by itself, `ask <serial> <what>
<choices>` when a pane asks a question (answered by `answer` on its ctl),
and `save <serial> <name>`,
`dump <path>` when a Dump is written and `restore <path>` in a Restore's
new log after its panes' `new`s, then `restored <old> <new>` for each pane,
-mapping the serial it had to the one it has now, and `msg <serial|-> <text>`
+mapping the serial it had to the one it has now, and `restoredcol <old>
+<new>` for each column, and `msg <serial|-> <text>`
for every line the editor says, repeats included (with `verbose` on, that
-includes each builtin announcing itself as it runs), and `err <serial|->
+includes each builtin announcing itself as it runs, on purpose: the log says
+which ran; its serial is the pane it ran at, `-` when the keyboard was on a
+column or workspace tag), and `err <serial|->
<file>: <why>` for every write or truncation the tree refused or that
failed -- through a mount a shell sees only the errno its kernel mapped the
reply to, usually `Invalid argument`, and this is the reason (`err 3 addr:
@@ -547,7 +605,8 @@ Control characters in a record become spaces, so a record is one line.
(An `event` record is not: acme's `<origin><action><q0> <q1> <flag> <n>
<text>\n`, whose text may hold newlines. The origin is `E` (a 9P write to body or tag), `F` (other
files, the editor's own lines), `K` (the keyboard) or `M` (the mouse); the
-action's case says where: `x`/`l` a click executed or looked at in the tag,
+action's case says where: `x`/`l` a click executed or looked at in the tag
+(its offsets count the tag's whole text, path included, as `tag` reads),
`X`/`L` in the body, `I`/`D` text put in or taken out of the body, `i`/`d`
of the tag. Read `n` bytes of the text, not up to a newline -- bytes here, where acme counts runes. Every offset and
count pardes serves is in bytes, `#n` and `q0`/`q1` too; the event count
@@ -645,8 +704,9 @@ Fid), released on close or disconnect; past that such an open fails with
`-Dembed-sources=true` embeds the editor's sources and serves them under
`/src` (and `/shaders` on GUI builds). `EffectCode <effect>` lists the current
backend's implementation files under `/virtual`, which Look opens; without the
-option the command reports the sources as unavailable. The esp32p4 build
-enables the option by default, so the device can serve its own source.
+option the command reports the sources as unavailable. It is off by default
+everywhere; the esp32p4 image in particular has no room for them (~1.8 MB of
+source against a 1.5 MiB app partition).
This is a control filesystem, not a complete POSIX export. Native filenames
may contain up to 255 bytes. Existing regular OS files support read, write,