diff options
Diffstat (limited to 'docs/fs.md')
| -rw-r--r-- | docs/fs.md | 130 |
1 files changed, 96 insertions, 34 deletions
@@ -61,6 +61,8 @@ private namespace: 9ns --unix "$PARDES_9P" -- sh -c 'cat "$NINE_MOUNT/index"' ``` +(Under `9ns --unix`, `$NINE_MOUNT` is that session's root itself.) + A `9ns --unix` mount lives in the private namespace of the command it runs, and nothing outside that command sees it. The mount everyone on the machine shares is the registry one, `9ns --mntgen` (default `/mnt/9p`): every running @@ -127,7 +129,9 @@ Restore puts a new editor under every client, so the write of it is answered and then every connection is hung up, their fids naming the old editor's panes (a 9ns older than cloud9 2a7137c could fail the write with ECONNRESET all the same, when another request's send met the hang-up -before the answer was read; the log is the authority): dial again, and the new +before the answer was read; the log is the authority): dial again -- a 9ns +mount is one such connection, so after a Restore stop it and start 9ns +again, or every file under it fails -- and the new log names the restored panes and `restore <path>`. The answer has 200 ms to leave before the cut, so a slow client may see only the cut; the log's `restore <path>` is what says the @@ -137,16 +141,18 @@ never needed); and `Kill`, which does not quit but stops commands, as acme's does: bare, every command pardes started, and `Kill make ls`, those whose line begins with one of the words. A command pardes started is a command pane's, until its child exits -- Kill -sends its whole process group SIGTERM -- or a line it typed into a terminal (a +sends SIGTERM to its running job and to its shell, so the whole line stops +(of `sleep 30; echo done` the `echo` never runs) -- or a line it typed into +a terminal (a word written to `exec`, a middle click on one, a `pty/run`), from its shell's start mark (C) to its end mark (D), where Kill sends its foreground job SIGTERM -- acme posts the "kill" note, which ends a process -- and never signals the shell itself; 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 only the -foreground job, so of `sleep 30; echo done` the `echo` still runs once the -`sleep` is stopped -- +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 -- 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 @@ -249,23 +255,32 @@ same tree without leaving the process. `src/builtins.zig` (`Save`, `Del`, `New`, `Newcol`, `Mount NAME DIAL`, `Unmount NAME`, `Dump`, `Restore`, `Msg TEXT`, `Find`, `Grep`, `Tty`, ...), or anything else, a command line. Written at a terminal at its prompt it - is typed into that shell. From anywhere else -- a file, a scratch, a tag, + is typed into that shell (and a terminal whose shell exits, `exit` typed + or run, closes its pane). From anywhere else -- a file, a scratch, a tag, a terminal whose tty a program holds -- it runs as a command pane: a terminal whose child is the root ctl's `Shell` (fish unless set) run - with `-c` and the line, in the pane's directory, + with `-c` and the line, in the pane's directory, with job control on + (bash, sh, dash, zsh, ksh `-m`; fish `status job-control full`), which shows its output and then `exit N` (its tag reads `<dir> (<line>) running`, then `exit N`), and stays. The command is over when its process exits, as in acme, not when its terminal closes: a job it left in the background prints on below `exit N` until it lets go of the pty, and a - command that lets go of its terminal early runs on to its own exit. The directory's next command runs in - that pane once it is done, below what it showed, after a `% <line>` line; + command that lets go of its terminal early runs on to its own exit. A + background job outlives the command: job control gives it a process + group of its own, so the hangup the kernel sends the terminal's + foreground group when the shell exits misses it. It survives the pane + closing too, but its writes to the terminal then fail, so start one that + must keep writing with `nohup` or its output redirected. The directory's + next command runs in that pane once it is done and nothing holds its pty, below what it showed, after a `% <line>` line; one still running gets a second pane. Before the next command the pane leaves any alternate screen and turns off the modes a program left on (mouse reports, bracketed paste, a hidden cursor); a command that clears the screen and its scrollback (`clear`, ED3) erases the history above it. A command pane's own exec starts the next command there too. The log says `run <serial> <line>` and `exit - <serial> <N|?>`; `exec` reads back the command pane's serial; Kill ends - its whole process group; a line is at most 1 KB. A misspelled word is a + <serial> <N|?>`; `exec` reads back the command pane's serial; Kill stops + its whole line; a line is at most 1 KB. To run a command again, execute + its line again from its directory: `echo 'make test' > pane/<n>/exec` on + the command pane runs it there, below the last run. A misspelled word is a command that says so and ends `exit 127`. `echo Tty > pane/<n>/ctl` makes an interactive terminal in that pane's directory. @@ -296,7 +311,9 @@ the tag is how to run `make` from that file), `Exec <text>` run by name 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`), since line by line a blank line ends a Python block and Python +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 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. @@ -312,12 +329,18 @@ not the hits buffer it opened. A look takes acme's addresses after a colon (editors/acme/look.c:450): a line written to `look` as `file:/re/`, `file:#n`, `file:$` or any address -opens (or finds) the file and selects what the address names, evaluated -from its dot; `:addr` does the same in the pane itself. `file:12` and -`file:12:5` stay line and column. A bare `/re/` is a path, as in acme, and -failing that a search for its text. A look that finds nothing, or an -address that does not evaluate, says so on the message row and changes -nothing: no buffer opens and the selection stays. +opens (or finds) the file and selects what the address names. **The +address is evaluated from the file's dot**, as acme's is: `file:/re/` +finds the next match after the current selection, not the first in the +file. For the first, start at the top: `file:0/re/` (or `file:#0/re/`). +`:addr` does the same in the pane itself, and a pattern may hold blanks +(`calc.py:/return a/`). `file:12` selects line 12, its newline included, +as acme's does; `file:12:5` puts the caret at line 12, column 5. A bare +`/re/` is a path, as in acme, and failing that a search for its text. A +look that finds nothing, an address that does not evaluate, or a line past +the file's end (`calc.py:99`) says so on the message row and in the log +(`err <serial> look: ...`), focuses and opens nothing, keeps the +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 @@ -344,7 +367,13 @@ tab width — followed by rio's `current` or `notcurrent` (rio(4), `wctl`): whether the pane has the keyboard. It takes the pane's builtins (below), `get`, which reloads the buffer from the name it carries (unsaved edits are refused once, `<name>: Modified (get again to -discard)`, as acme's get asks winclean, exec.c:513), and acme's `lock` and `unlock` (editors/acme/xfid.c:603-611), for an +discard)`, as acme's get asks winclean, exec.c:513), `answer <choice>` +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), +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 it: a `lock` while another open holds it fails at once with `file in use` @@ -365,14 +394,19 @@ they also accept, so copying one onto another is all that acme's `addr=dot`, address expression (`#0,#5`, `/pattern/`, `2+1`, and pardes's own `12:5`, below); `addr` selects what `data` and `xdata` read or replace, `dot` is the editor's own selection and moving it -scrolls the pane into view, and `limit` bounds a search and reads empty until -it is set. Truncating `dot` empties it, truncating `limit` lifts it, and +scrolls the pane into view, and `limit` bounds only the end of a forward +search, as acme's does, and reads empty until it is set. Truncating `dot` empties it, truncating `limit` lifts it, and truncating `addr` leaves it as it is (below). A rename everywhere, or any other sam edit, is one write to the pane's `ctl`: `Edit ,x/foo/c/bar/` runs acme's Edit (docs/tags.md) on the body as one undo step; a failure fails the write with acme's words and changes -nothing. +nothing. A write is one message a line, except that an `Edit` line takes +the lines after it while its `{` group is open or its `a`, `c` or `i` text +block waits for its `.` line, on a pane's `ctl`, the root's (at the active +pane) and `exec` alike; an unclosed group is refused (``unmatched `{'``). +bash's builtin `printf` writes a line at a time, so write a block with a +heredoc or `env printf`. `line:col` is a pardes extension to sam's addresses, the spelling Look takes in `file:12:5`: `12:5` is the point at line 12, column 5, and it @@ -406,7 +440,15 @@ lazy `*?` included), searched the way sam searches (editors/acme/regx.c): as lines, so `^` and `$` match at the start and end of any line, `.` and a negated class never match a newline, and `$` also matches at the end of a text with no final newline. A pattern that names a newline (`\n`) runs over -the whole text instead, its `.` kept to one line. An expression is +the whole text instead, its `.` kept to one line; there a leading `^` still +matches at every line start, and `$` may stand just before a `\n` (where it +changes nothing). Any other `^` or `$` in such a pattern, `(^|\n)def` or +`a\nb$`, is refused with `in a pattern with \n, ^ can only come first and $ +only just before a \n`, since mvzr would read it as the start or end of the +whole text: never a search that silently finds nothing. Within a line, `^` +inside an alternation (`^def|^ `) matches only where the search starts, so it +works from a line's start (an `x` over lines, a `g` on one) and not from its +middle: an mvzr limit. An expression is evaluated from the current address, the range last written to `addr` (or left by the last `data` write, just past it), as acme evaluates it from `w->addr` (xfid.c:446): `.` is that address, not the selection (`dot` is @@ -448,13 +490,15 @@ The three flag files `dirty`, `mark` and `scroll` read `0` or `1` and take an undo point (writing `1` pushes one now), and whether a write scrolls the pane. -`tag` reads the whole tag as the pane shows it: the computed path, dirty -marker or PDF page, then the text you may edit. A write appends to that text, +`tag` reads the whole tag as the pane shows it: the computed path or PDF +page (no mark for unsaved text: the grip shows that, and `dirty` says it), +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. The clearing is an edit of the tag like a typed one and its undo +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 history is kept: `u` in the tag brings back the text it cleared, words included. @@ -472,9 +516,13 @@ 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, -since a terminal is named by its directory) and `save <serial> <name>`, +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, and `msg <serial|-> <text>` +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>` for every line the editor says, repeats included (with `verbose` on, that includes each builtin announcing itself as it runs), and `err <serial|-> <file>: <why>` for every write or truncation the tree refused or that @@ -497,8 +545,11 @@ pane is being made can precede that pane's `new`; panes present at boot are recorded before anything else. 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; read `n` bytes of it rather than -up to a newline -- bytes here, where acme counts runes. Every offset and +<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, +`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 follows them rather than switch alone, so an acme library reads pardes correctly for ASCII text and not beyond it. A `#n` that falls inside a @@ -545,8 +596,14 @@ are read so that the answer costs the editor a bounded amount. `exit ?` is a command whose end mark carried no status, which is not a success; `error out of memory` is an answer that could not be made. The header is always the whole first line. It reads -`busy` at once when a command is running or text is typed at the prompt, -which is also when the third field of `pty/status` reads 1. A line written +`busy` at once when a command is running or text is typed at the prompt +-- a run is a line typed at the shell's prompt, so a program holding the +terminal (a REPL, `less`) takes none: write to `pty/data` for it -- +which is also when the third field of `pty/status` reads 1. `pty/status` is +one line, three right-aligned fields and a newline: the pty's columns and +rows, then busy (0 or 1). The size, and `pty/ctl`'s `winsize` read back, is +what `winsize C R` last set, until the pane itself resizes and gives the pty +its grid again. A line written before a new terminal's shell has drawn its first prompt is not busy: it waits for that prompt (a respawn meanwhile keeps it waiting for the new shell's) and is sent then, so the first command a script gives a fresh @@ -555,8 +612,13 @@ could not instrument, or a startup that hangs) leaves such a line waiting for ever: cancel the read (interrupt it, or close the open) to give up; `error not run` when the shell refused the line without running it (a fish syntax error; the line is taken back off -the prompt); `error shell gone` when the pane closed or its shell was -replaced; `error no prompt marks` for a shell pardes could not instrument; +the prompt): the shell's marks say only that it did not run, so the answer +carries no reason or code, and the shell's own complaint is in the pane's +body (`tail body`); `exit N` and what it printed when the line ended the shell +itself (`exit 3`, or `echo bye; exit 3`): its terminal closes, and a read +of the run's open still answers after the pane is gone; `error shell gone` +when the pane closed or its shell was replaced, or the shell went without +an exit status to tell; `error no prompt marks` for a shell pardes could not instrument; `error command done; not a shell` (or `error a command runs here, not a shell`) on a command pane, whose child is its command. It relies on the OSC 133 marks pardes injects into bash and fish, tagged |
