Deliver the keys that are not characters

An arrow key has never reached this machine. Voyager threw it away for want of
anywhere to put it, and a terminal sent ESC [ A, which arrived in the middle of
whatever was being read and made it unrecognisable - typing Up at the CosmOS
prompt put three bytes in the command line and got "I do not know".

So the console names them: one byte each, 0x80 upward, above ASCII so nothing
written before them can collide. Up, Down, Left, Right, Home, End and forward
Delete, with room above for the paging and function keys.

The console normalises, which is what it already does. Behind a window it turns
the key somebody pressed into a byte; on a terminal it turns the sequence into
the same byte. That is the act it has always performed on Return and Backspace,
one layer further along, and it is why a program need not know which of the two
it is talking to. What a key MEANS is not the console's business - that belongs
to whoever is reading, the same way what is on a disk belongs to the system and
what a drive is belongs to the machine.

Translated only when standard input really is a terminal. Nothing else sends
these sequences, a pipe holds exactly the bytes somebody put in it, and it keeps
the Escape-or-Up timing problem out of every test here: a test writes the key
values themselves. Line mode drops them, in both front ends, because line mode
delivers characters and a line somebody else has finished editing cannot be
moved about in.

Press.sbx says what it was handed, in hexadecimal and by name, and reads a line
before it reads keys so both halves of that rule are checked. Two recordings,
one fed as standard input and one as a keyboard, agreeing byte for byte; each
break fails exactly one of them. Three checks in terminal.sh type real escape
sequences at a pseudo-terminal, which is the only place they are ever read as
sequences: that they arrive as keys, that Escape alone is still Escape, and that
a character typed straight after an escape is held rather than swallowed.

Five recordings re-blessed for Press.sbx appearing on the shared disk, and the
whole of that diff is the file's own line and the counts above it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-31 22:24:11 -04:00
co-authored by Claude Opus 5
parent 2a29cebc6b
commit b3726c950a
17 changed files with 646 additions and 35 deletions
+11 -1
View File
@@ -79,7 +79,7 @@ from `make`, not from here.
### 1. Recorded output
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
everything it printed against a file in `Tests/expected`. 186 tests, of which 124 run, 35
everything it printed against a file in `Tests/expected`. 188 tests, of which 126 run, 35
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
given at all.
@@ -219,6 +219,16 @@ that a prompt arrives before input is read, that a keystroke arrives without Ret
the terminal is handed back however the machine dies - SIGHUP, SIGINT, SIGQUIT, SIGABRT,
SIGSEGV, SIGTERM - and that suspending and resuming leave it as they found it.
**And it is the only place an escape sequence is ever read as one.** A terminal sends
`ESC [ A` for the Up key and the console turns that into a byte of its own, but only when
standard input really is a terminal - everywhere else in this suite the input is a file,
which holds exactly the bytes somebody put in it and goes straight past the translation. So
three checks here type at a pseudo-terminal: that the sequences arrive as keys, that Escape
pressed on its own is still Escape, and that an ordinary character typed straight after an
escape is held rather than swallowed with the sequence that never was. The recorded tests
cover the other half - what a program does with the key values - by writing them into the
input file directly.
It also asks the one question about *waiting* that nothing else can, since the count is
stripped from every recorded result: whether a program on a slow disk slept through the wait
or spun on it. Both print the same characters and take the same elapsed time. Only the split