The Machines · Graphics & interaction

terminal

The Console Itself — machines/terminal.shoddy

the terminal machine's icon

Summary

terminal is where Shoddy's raw console words are written down: Print to put a line on the screen, Input and InputLine to read one back, InKey to catch a single keystroke without waiting, and Args to see how the program was started. This machine declares no words of its own. All five are builtins — the engine dispatches them, running each itself. They are callable from any program with no Include at all, and including this file gives you nothing you did not already have. The page exists so that a reader who goes looking for "how does a Shoddy program read a keystroke?" finds the answer in a machine named for the question. Otherwise the reader would need to already know that the flat word reference exists.

A Brief History of the Teletype

Print is called Print because it printed. The console the early timesharing systems (computers many people shared at once) and the first BASICs talked to was a Teletype — typically the Model 33, a typewriter-telegraph hybrid hammering ten characters a second onto a roll of paper. The programs of that era were shaped by it. Output came a line at a time, because a line was what the carriage could do. Input came a line at a time, because nothing existed until the operator pressed Return. The paper gave way to glass and the glass to windows, but the contract never changed. That is why it is still called a tty (short for teletype) in every operating system, why lines remain the unit of console conversation, and why the five words on this page are all a console program truly needs. Only InKey is a child of the later, faster hardware: a single keystroke, caught without waiting, is a thing a glass terminal can offer and a ten-character-a-second printer never could.

Why It's Useful

Every builtin in the language lives in exactly two places that a reader can reach: section 10 of the spec, which is one long list grouped by rough category, and the compiler's own effects table, which is C#. Neither is reachable from the thing you were actually thinking about. If you want to know how to read a key, you do not think "I should consult the flat reference" — you think "keyboard", and you go looking for a machine. Most of the library answers that instinct, because the builtins a domain is built on are documented in the machine that owns the domain. The console words had no such machine, so they had nowhere to be found. This is that machine.

Nothing here is new and nothing here is a wrapper. If you want convenience verbs on top of these — a prompt-and-validate loop, a menu reader — those would be ordinary Defs and would belong in a program or a machine that declares them. What is documented below is exactly what the runtime gives you, described where you would go looking for it.

User's Guide

You need no Include for any of this. The words below are already in scope in every Shoddy program.

Def Main()
    Print("What is your name?")
    Let who = Input("> ")
    Print("Hello, " & who)

    ' a non-blocking poll, the shape a game loop wants
    Let k = InKey()
    If k <> "" Then
        Print("you pressed something")

A few things worth remembering:

One distinction is worth getting straight, because it decides which of two machines you want. terminal is the raw console: putting characters out, taking characters in. vt100 is the protocol spoken over it: the escape sequences that move a cursor or set a colour, and the decoder that turns a raw arrow-key sequence into a named key. Reading a keystroke is not a VT100 idea — InKey is the same word on a terminal that has never heard of DEC. Interpreting what comes back is entirely a VT100 idea. So the raw words are here, EvalKey stays there, and neither machine includes the other.

Builtins

The four console words the runtime dispatches, plus Args

None of these is a Def. The engine dispatches them — runs them itself — and a Def whose name is a builtin is refused. The same five are documented word for word in machines/terminal.shoddy's own header block. Stack effects — what each word takes and leaves — are the ones the compiler's Effects.cs table declares.

Writing

WordDescription
Print(s)Write s to the screen, followed by a newline. There is no write-without-newline builtin, so build a line up with & and print it once.

Reading

WordDescription
Input(prompt)Print the prompt, read one whole line, answer it as a String. Numbers come back through Val — or better, IsNumeric and then Val. End of stream and a blank line both collapse to "".
InputLine(prompt)The same read, answering a 2-element Array [atEof, text]: element 1 a Boolean, True only at genuine end of stream; element 2 the line, empty at EOF. It is a flat Array rather than a record because a builtin cannot reach a Type — lifting it into a sum type (a type with named alternative cases) is the caller's job, which is what halifax does in HxAskedOf.
InKey()One pending keystroke, read without blocking and without echo, or "" when none is pending. Arrow keys and PF1–PF4 arrive as their VT100 application-mode escape sequences, which is what vt100's EvalKey decodes.

The invocation

WordDescription
Args()The arguments the program was started with, as a List Of String. Also available in native hosts — not terminal-exclusive. Unlike the four above, a console is not this word's only home: a headless service or a program launched from a desktop has arguments too, with no terminal involved anywhere. The spec classifies it as core, and it is documented here because reading your own invocation is a console-shaped thing to want.

Who Uses It

Nothing includes it, and nothing needs to. This machine declares no words, so there is nothing to import; the five builtins it documents are in scope everywhere already. The pages that lean on it are documentation rather than code — vt100 points here for Print and InKey rather than claiming them.

The Machines It Uses

None, and it could not use one — a file that declares nothing has nothing to build. It includes no machine and no machine includes it.