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:
co-authored by
Claude Opus 5
parent
2a29cebc6b
commit
b3726c950a
@@ -281,10 +281,36 @@ The control port's two bits are independent, and one write sets both. Everything
|
||||
|
||||
In **line mode**, which is how the machine starts, the terminal holds what is typed until Return and does the echoing and the backspacing on the way. A program reading the data port gets a finished line, one byte at a time. This is what the machine has always done and what a shell wants.
|
||||
|
||||
In **key mode** the terminal stops holding the line. Keys arrive as they are pressed, and nothing echoes them, so a program that wants them seen has to send them back out itself. The editing goes with the echo: there is no backspace, because backspace was the terminal's doing and the terminal is no longer involved. That is not a choice this machine makes, it is what asking for keys means, and a program that wants keys is expected to want it.
|
||||
In **key mode** the terminal stops holding the line. Keys arrive as they are pressed, and nothing echoes them, so a program that wants them seen has to send them back out itself. This is also the only mode in which the keys that are not characters arrive at all - see below. The editing goes with the echo: there is no backspace, because backspace was the terminal's doing and the terminal is no longer involved. That is not a choice this machine makes, it is what asking for keys means, and a program that wants keys is expected to want it.
|
||||
|
||||
A program is expected to put the console back in line mode before it finishes. CosmOS also does it whenever a program returns, because a program that stops early would otherwise hand back a shell with no echo, and a shell has no way to find out that happened.
|
||||
|
||||
### Keys That Are Not Characters:
|
||||
|
||||
An arrow key is not a letter, and for a long time there was no byte for one, so it did not reach this machine at all: a window threw it away for want of anywhere to put it, and a terminal sent an escape sequence which arrived in the middle of whatever was being read and made it unrecognisable.
|
||||
|
||||
The console names them now. Each arrives as one byte, above ASCII so that nothing written before them can collide:
|
||||
|
||||
| Byte | Key |
|
||||
| --- | --- |
|
||||
| 0x80 | Up |
|
||||
| 0x81 | Down |
|
||||
| 0x82 | Left |
|
||||
| 0x83 | Right |
|
||||
| 0x84 | Home |
|
||||
| 0x85 | End |
|
||||
| 0x86 | Delete, meaning the character under the cursor |
|
||||
|
||||
Backspace is 0x08 and always has been. It is a different key from Delete and does a different thing, which is why they are two values and not one.
|
||||
|
||||
0x80 to 0x8F belong to the console, so a program can tell a key from a character by testing that range. The values above 0x86 are not used yet.
|
||||
|
||||
**The console normalises, which is what it has always done.** Behind a window it turns the key somebody pressed into a byte; on a terminal it turns `ESC [ A` and its neighbours into the same byte. That is the same act it performs on Return and Backspace, and it is why a program does not have to know which of the two it is talking to. The translation happens only when there really is a terminal: a file or a pipe holds exactly the bytes somebody put in it, and a program reading one gets those bytes untouched - which is also how a test presses an arrow key.
|
||||
|
||||
**These arrive in key mode only.** Line mode delivers characters, and a program in line mode is being handed a line that something else has already finished editing, so a key meaning "move the cursor left" arrived too late to mean anything. The console drops them there. This is what a terminal does too: it has always given a program in line mode backspace and line kill, and has never given it arrow keys.
|
||||
|
||||
**What a key means is not the console's business.** Where the cursor goes, what the line looks like afterwards and what was typed before are all decisions, and decisions belong to whatever is reading - which on this machine is usually CosmOS, whose shell edits its own line. The console says which key was pressed and stops there, exactly as the disk says what a drive is and says nothing about what should be on it.
|
||||
|
||||
### Reading Without Waiting:
|
||||
|
||||
Reading the data port waits in **both** modes. The status port is how a program declines to wait, and keeping that in one place is deliberate: a read that sometimes blocked and sometimes did not, depending on a mode set somewhere else, would be a program that works until it does not.
|
||||
|
||||
Reference in New Issue
Block a user