Standardbibliothek
Antra::Console
import Antra::ConsoleHigh-level interactive console I/O for shell scripting.
Antra::Console provides ask / confirm / menu on top of Antra::IO
(line and key input) and Antra::Terminal (colours). For raw ANSI sequences
use Antra::Terminal; for raw line/byte I/O use Antra::IO.
All entry points run against a session — a %ConsoleIO{reader, writer, is_tty} value. The default session wraps the real stdin/stdout; tests (or
custom drivers) can pass their own via the io: option, which makes the
package fully testable without a TTY.
import Antra::Console as Console
import Antra::Validator as V
val name = Console.ask("Name?", [default: "anon"]).^
val port = Console.ask_int("Port?", [validator: V.value_range(1, 65535)]).^Interaktive Konsolen-Ein-/Ausgabe für Shell-Skripte: getippte Eingaben abfragen
(ask), Ja/Nein-Fragen stellen (confirm) und aus einer Liste auswählen
(menu) — mit Defaults, Validierung, Re-Prompt bei Fehleingabe und optionaler
Passwort-Eingabe.
Import#
import Antra::Console as ConsoleAntra::Console sitzt auf Antra::IO (Zeilen-/Tasteneingabe) und
Antra::Terminal (Farben). Für rohe ANSI-Sequenzen nimm Antra::Terminal, für
rohe Zeilen-/Byte-I/O Antra::IO; oft kombiniert man Console mit
Antra::Validator für die validator:-Option.
Überblick / Wann benutzen#
ask— eine Zeile Text einlesen, optional mit Default, Validierung und Typ-Coercion (parse:). Typisierte Kurzformen:ask_int,ask_num,ask_decimal.confirm— eine Ja/Nein-Frage mit[Y/n]/[y/N]-Hinweis.menu— eine nummerierte Auswahlliste; gibt das gewählte Element zurück (nicht den Index).
Jeder Aufruf gibt ein Result zurück; mit dem postfixen .! entpackst du es
direkt und wirfst bei %Err (z.B. Console.ask("Name?").!). Für
nicht-interaktive Konfiguration (CLI-Argumente,
Config-Dateien) ist Antra::Arg der passendere Baustein — dieselben
Antra::Validator-Bausteine funktionieren dort wie hier.
Konzepte#
Session (%ConsoleIO)#
Alle Einstiegspunkte laufen gegen eine Session —
%ConsoleIO{reader, writer, is_tty}. Ohne io:-Option wird eine Default-Session
auf die echte stdin/stdout verwendet. Tests oder eigene Treiber können über die
io:-Option eine eigene Session übergeben, wodurch das Paket komplett ohne TTY
testbar ist.
Re-Prompt und Defaults#
Bei leerer Eingabe greift default:, falls gesetzt (der Default wird nicht
erneut validiert). Ohne Default und mit required: true (Voreinstellung) wird
die Frage nach einer Fehlermeldung erneut gestellt. Ein validator, der
%Err[msg] liefert, zeigt msg und fragt erneut.
Validierung und parse:#
validator arbeitet im String-Bereich (fn(String) -> Result[String]), damit
ask einheitlich Result[String] liefert und Validator.all/any komponierbar
bleiben. Wer einen echten Wert will, nutzt parse: (läuft nach erfolgreicher
Validierung und prägt den Rückgabetyp, Result[T]) oder die typisierten
Kurzformen. Ein %Err aus parse: löst ebenfalls einen Re-Prompt aus. Dieselbe
validator:-Konvention gilt auch bei Antra::Arg — eine Regel, überall.
Prompt-Färbung: color#
Die color:-Option (bei ask, confirm, menu und den typisierten Shortcuts)
färbt den Prompt-Text mit einem Antra::Terminal-Style (:cyan,
[:bold, :cyan], …). Sie greift nur auf einem TTY; auf Nicht-TTY-Ausgabe
(Pipe/Redirect) bleibt der Prompt plain, damit keine ANSI-Codes in Logs oder
Dateien landen. Auf einem TTY wird zusätzlich der [default]/[Y/n]-Hinweis
gedimmt. Für volle Kontrolle über das Format bleibt prompt_fn die Option, die
einen beliebigen (auch gefärbten) String liefert.
Abbrechen mit Ctrl-C#
Auf einem TTY ist jeder Console-Read immer abbrechbar: ein Ctrl-C während der
Eingabe liefert %Err[%Error{kind: :cancelled, message: "cancelled"}], statt den
Prozess zu beenden — die Zeilenbearbeitung bleibt normal (canonical mode). Das
gilt für ask, confirm, menu, die typisierten Shortcuts sowie die
hidden/mask-Pfade. Aufrufer können gezielt darauf matchen:
match Console.ask("Name?") {
%Ok[name] -> println("Hallo $name")
%Err[%Error{kind: :cancelled, ..}] -> println("Abgebrochen.")
%Err[e] -> println("Fehler: ${e.message}")
}Wird das %Err per .^ bis in den Root-Kontext propagiert, gibt der Interpreter
ERROR: cancelled auf stderr aus und endet mit Exit 1. Auf Nicht-TTY-Eingabe
(Pipe/Skript) gibt es kein Ctrl-C, also auch keinen Abbruch.
Verdeckte Eingabe: hidden und mask#
Für Passwörter auf einem TTY:
hidden: true— Terminal-Echo komplett aus; es wird gar nichts angezeigt (wie beisudo, verrät nicht einmal die Länge).mask: "*"— echot pro Zeichen die Maske statt der echten Eingabe; Backspace/Delete löschen sichtbar, Enter beendet, UTF-8 zählt als ein Zeichen.maskimplizierthidden(man musshiddennicht zusätzlich setzen).
Beide greifen nur auf einem TTY. Auf Nicht-TTY-stdin (Pipe/Skript) fällt die Eingabe auf einen normalen Zeilen-Read zurück, damit gescriptete Läufe funktionieren.
API#
ask(prompt) -> Result · ask(prompt, opts) -> Result#
Liest eine Zeile ein. Liefert %Ok[String] (bzw. %Ok[T], wenn parse: gesetzt
ist) oder %Err[%Error{...}].
Optionen (opts ist ein Keyword-Array):
| Option | Default | Bedeutung |
|---|---|---|
default: | undef | bei leerer Eingabe zurückgegeben und im Prompt gezeigt |
hidden: | false | Eingabe gar nicht echoen (Passwörter) |
mask: | undef | String wie "*" pro Zeichen echoen (impliziert hidden) |
required: | true | false erlaubt leere Eingabe → "" |
validator: | undef | fn(String) -> Result[String]; bei %Err Re-Prompt |
parse: | undef | fn(String) -> Result[T]; nach Validierung; prägt Rückgabe |
trim: | true | Whitespace vor Validierung/Rückgabe strippen |
prompt_fn: | undef | fn(prompt, default, hidden) -> String; eigenes Prompt-Format |
color: | undef | Terminal-Style (:cyan, [:bold, :cyan]) für den Prompt (nur TTY) |
io: | undef | Console-Session; Default = reale stdin/stdout |
import Antra::Console as Console
import Antra::Validator as V
val name = Console.ask("Your name?").^
val email = Console.ask("Email?", [validator: V.email()]).^
val token = Console.ask("Token?", [mask: "*", required: true]).^ask_int(prompt) -> Result · ask_int(prompt, opts) -> Result#
Fragt eine ganze Zahl ab und liefert %Ok[Number]. Kombiniert intern den
integer-Validator mit einer Zahl-Coercion; ein zusätzlicher validator: wird
davor gehängt. Optionen: default, required, validator, prompt_fn, io.
val count = Console.ask_int("Count?", [
default: "1",
validator: V.value_range(1, 20)
]).^ask_num(prompt) -> Result · ask_num(prompt, opts) -> Result#
Wie ask_int, akzeptiert aber Ganz- und Dezimalzahlen. Liefert %Ok[Number].
ask_decimal(prompt) -> Result · ask_decimal(prompt, opts) -> Result#
Fragt eine Dezimalzahl ab und liefert %Ok[Rat].
confirm(prompt) -> Result · confirm(prompt, opts) -> Result#
Stellt eine Ja/Nein-Frage und liefert %Ok[Bool] oder %Err[%Error{...}].
Akzeptiert y/yes/n/no (Groß-/Kleinschreibung egal). Eine leere Antwort
nutzt default, falls gesetzt; der Default wird als [Y/n] bzw. [y/N]
hervorgehoben. Optionen: default (ein Bool), prompt_fn, color, io.
if Console.confirm("Continue?", [default: false]).^ {
println("los")
} else {
println("abgebrochen")
}menu(options) -> Result · menu(options, opts) -> Result#
Zeigt eine nummerierte Auswahl und liefert das gewählte Element (im
Originaltyp, nicht den Index) als %Ok[T] oder %Err[%Error{...}].
Optionen:
| Option | Default | Bedeutung |
|---|---|---|
default: | undef | ein Element aus options, gewählt bei leerer Eingabe |
format: | str | fn(item) -> String zur Anzeige jedes Eintrags |
limit: | undef | höchstens N Einträge zeigen |
from_start: | true | mit limit: false zeigt die letzten N statt der ersten |
prompt_fn: | undef | eigenes Prompt-Format |
color: | undef | Terminal-Style für die Auswahlzeile (nur TTY) |
io: | undef | Console-Session |
val env = Console.menu(["dev", "staging", "prod"], [default: "dev"]).^
println("Ziel: $env")Fehler#
- Alle Funktionen liefern
%Err[%Error{...}]statt zu werfen; mit.!entpackst du und wirfst den%Error(fängt man mittry/catch), mit.^propagierst du ihn stattdessen als Wert. - Leere Eingabe bei
required: trueohnedefaultund ohne verfügbare weitere Eingabe (EOF/Nicht-TTY) endet in%Errmit einer „a value is required"-Meldung — interaktive Skripte, die ohne stdin laufen, sollten daher Defaults setzen oderrequired: falseverwenden. - Ein am Top-Level nicht abgefangenes
%Err[...]aus.^gibtERROR: <message>auf stderr aus und beendet mit Exit 1.
Siehe auch#
- Beispiele:
examples/console_ask.ant,console_confirm.ant,console_menu.ant,console_hidden.ant - Quelle:
lib/Antra/Console.ant - Verwandt:
Antra::Validator,Antra::Terminal,Antra::IO, Arg-Referenz für nicht-interaktive CLI-Eingaben - Spec:
specs/spec_console_package.md
Funktionen#
fn ask(prompt)
fn ask(prompt, [
default: = undef,
hidden: = false,
mask: = undef,
required: = true,
validator: = undef,
parse: = undef,
trim: = true,
prompt_fn: = undef,
color: = undef,
io: = undef
])Asks for a line of input. Returns %Ok[String] (or %Ok[T] when parse:
is set), or %Err[%Error{...}].
Options: default, hidden, mask, required, validator, parse,
trim, prompt_fn, color, io. mask (a string like "*") implies
hidden and echoes the mask per character on a tty. color (a Terminal
style like :cyan or [:bold, :cyan]) paints the prompt on a tty; the
[default] hint is dimmed there too. On a tty, Ctrl-C during the read
always yields %Err[%Error{kind: :cancelled}] instead of killing the
process. See the package doc and the Console spec.
Example:
Console.ask("Your name?").^
Console.ask("Port?", [default: "8080", validator: V.integer()]).^fn ask_decimal(prompt)
fn ask_decimal(prompt, [default: = undef, required: = true, validator: = undef, prompt_fn: = undef, color: = undef, io: = undef])Asks for a decimal number. Returns %Ok[Number].
fn ask_int(prompt)
fn ask_int(prompt, [default: = undef, required: = true, validator: = undef, prompt_fn: = undef, color: = undef, io: = undef])Asks for a whole number. Returns %Ok[Number]. Accepts the same options
as ask (a validator is combined with the built-in integer check).
Example:
Console.ask_int("Count?", [default: "1"]).^fn ask_num(prompt)
fn ask_num(prompt, [default: = undef, required: = true, validator: = undef, prompt_fn: = undef, color: = undef, io: = undef])Asks for an integer or decimal number. Returns %Ok[Number].
fn confirm(prompt)
fn confirm(prompt, [default: = undef, prompt_fn: = undef, color: = undef, io: = undef])Asks a yes/no question. Returns %Ok[Bool], or %Err[%Error{...}].
Accepts y/yes/n/no (case-insensitive). An empty answer uses
default if set; the default is highlighted as [Y/n] or [y/N].
Options: default (a Bool), prompt_fn, color, io. On a tty, Ctrl-C
yields %Err[%Error{kind: :cancelled}].
Example:
if Console.confirm("Continue?", [default: false]).^ { ... }