syst
sysk describes; whatever shows it lays out. The shell says what its answers are: text, a value, or a word of its own such as the prompt. The terminal carries them. A host on the person's machine draws them: a run of records as a table, at the width the person's terminal really has. On a plain serial line nothing changes, so sysk is never unreadable.
Three places, one job each
Unix puts a tty between a program and the person: a line discipline in the kernel that echoes, edits and turns Ctrl-C into a signal, with escape codes for anything more. sysk's terminal does almost none of that (sysk 015): the person's end edits the line and sends it whole. syst takes the next step. Programs no longer format for a screen at all. The shell knows what each answer is, the terminal task carries it, and the host decides how it looks.
The shell and the terminal run in sysk, on the RISC-V machine; the host runs on the person's machine, at the other end of the serial line: tools/attach.rkt, which make run starts. Select a box.
What the shell says
An answer is a line of 64 bytes, as since sysk 013: byte 0 is the length of the text that follows. The length is below 64, so its six bits leave two over, and since sysk 044 they say what the text is. The shell's say sets them: a line that is exactly one s-expression is a value (sx-one), anything else is text. The prompt and the region numbers are the shell's own, control. A value longer than a line goes in pieces that the next answer continues, so a value is always whole by the time anything shows it.
| Kind | Bits | Text | Shown on a plain line | Sent to a host |
|---|---|---|---|---|
| text | 00 | any line | as it is | (text "…"), quoted |
| value | 01 | one s-expression, or its last piece | wrapped between its fields | (out VALUE) |
| more | 11 | a piece of a value; the next answer goes on | held until the value is whole | held until the value is whole |
| control | 10 | (prompt "sysk> "), (region 3) | the prompt, unfinished; regions not at all | as it is |
Nothing a program prints can pass for the shell. The kind is in byte 0, never in the text. A job's lines are clamped to text when the shell relays them, and a file that holds (region 9) is said as a value, so a host receives (out (region 9)): data, never control. The same rule will carry the trusted path later (docs/authority.md): only the terminal task can write outside these messages.
On the wire
A host says (syst 1) as its first line. The terminal answers it and from then on writes one message a line, and reads one: what the person types comes as (line "…"), in pieces of at most 63 bytes as a plain line longer than a message is, and the end of input as (eof). Before that, or with no host at all, the terminal shows everything as it always has. One session, both ways: the person types cat /sys/task/*/status, then uptime (abridged to four of the ten tasks).
on the serial line
what the person sees
What the person types is shown by their own terminal, not sent back by sysk. The messages are what the boot tests check (tests/boot-test.rkt); the layout is a function of the messages alone, tested without a machine (tests/syst-test.rkt).
Values, a *, and where
Three small things in the shell make values worth having. cat says a whole line that is one s-expression as one value, however long. A path may have one component that is *: cat /sys/task/*/status is cat of each task's status, in the directory's order. And where keeps the values that have a field: (where (state live) (cat /sys/task/*/status)). Each is the shell's, because each is about what a command means; none knows how anything looks.
sysk> (where (from terminal) (cat /sys/chan/*)) name bytes depth queued ended from to screen 64 2 0 no terminal uart-driver lines 64 1 0 no terminal sugar
where filters what cat shows, for now: around anything else it says so. A path with a * is made in the job table's buffer, free while a file is shown, and the directory is read again for each name, since showing a file uses the reply buffers; a directory of 64 names at most.
The host
tools/syst.rkt is the layout, and tools/attach.rkt the relay that uses it: QEMU's serial line on one side, the person's terminal on the other. It holds a run of values in one region. When the run ends (text, a prompt, another region, a value of another shape), it is laid out: two or more records with the same head and keys, each field an atom, are a table if it fits the terminal's width; anything else is written as it is, wrapped between fields, and inside a string between words, so a long string is never cut (sysk 057). A line from a region older than the newest, a job in the background, carries that region's number. make run speaks syst; tools/attach.rkt --plain relays the bytes as before; --pt hands the line to postterm's pt-attach.
Tab
At a terminal the host edits the line itself (sysk 050): sysk never edits, and the canonical mode of a terminal cannot see a Tab. On Tab, while sysk waits for a line, it sends (complete WORD ...), the line so far as words, and takes the shell's choices out of what comes back before the next prompt, without showing them as output. One choice is filled in whole; several fill in what they share; when they share nothing more, they are shown in columns under the line, and the line comes back. Inside (where (FIELD VALUE) ...) the host does not ask: a value describes itself, so the records it last laid out are the fields there are and their values, and Tab offers those (sysk 051): cat /sys/task/*/status, then (where (st⇥ is (where (state , and l⇥ is live. Up and down walk the lines typed before; Ctrl-U empties the line. Lines a job prints in the background come above the line being typed, which is drawn again under them. With --plain, or with no terminal, the host edits nothing, as before.
sysk> cat /sys/task/s⇥ /sys/task/sugar/ /sys/task/shell/ /sys/task/slot-0/ /sys/task/slot-1/ /sys/task/slot-2/ /sys/task/slot-3/ sysk> cat /sys/task/sl⇥ sysk> cat /sys/task/slot- sysk> follow /log --q⇥ sysk> follow /log --quiet
The choices are values the shell said, (choice (word /sys/task/sugar/) (kind dir)); their words are what the host shows. What a program accepts and what Tab offers come from one place, the catalogue the job check judges by.
Not yet: watch laid out in place, a region drawn again whenever what it shows changes (the shell's watch, sysk 049, says each change as a new value today); results kept as files, /res/3; a line only the terminal task may write, for the trusted path; and postterm as a host, through the upgrade its line form designs.