caique/ask
Every export of caique/ask, with its signature and doc comment: ask, projection, plus 6 types.
The six widgets, in line mode (R5) — and line mode is not a fallback, it is the floor.
Every widget here works by writing a question and reading a line. No raw mode, no cursor
movement, no escape sequence, no redraw. That makes it the accessible mode by
construction rather than by a second implementation kept in step by hand: a screen
reader gets the same bytes a terminal does, and select is a numbered list because a
numbered list is what a person can answer without seeing a highlight move.
It is also what makes the widgets testable without a PTY. A Reader is one method that
returns the next line, so the whole suite is strings in and strings out; the raw-mode
renderer that arrows and highlights will come later sits on top of this and answers
the same questions, which is how it stays honest.
Nothing here reads process, and nothing decides whether to ask — that is decide(),
which runs first and refuses when there is no one to ask.
import { ask, projection } from 'caique/ask';Functions
ask
Ask one prompt and return its answer.
A stream that ends is a cancellation, not an empty answer: Ctrl-D and a closed pipe
both mean nobody is going to type, and treating that as '' is how a program ends up
writing to a path the user never chose. Invalid input is re-asked, bounded — after
MAX_ATTEMPTS it gives up rather than looping, because a loop against a stream that
keeps answering wrongly is the hang this package exists to prevent, wearing a hat.
function ask(prompt: BoundPrompt | PromptSpec, io: Io): Promise<Asked>;| Parameter | Type |
|---|---|
prompt | BoundPrompt | PromptSpec |
io | Io |
Returns Promise<Asked>
projection
What a widget would have written, without reading anything — the static projection (U3).
The docs gallery, --help and a transcript in an issue all want the question without
the conversation, and every other package in this family can answer that; so does this.
function projection(spec: PromptSpec): string;| Parameter | Type |
|---|---|
spec | PromptSpec |
Returns string
Interfaces
Io
interface Io {
reader: Reader;
writer: Writer;
}Reader
A line of input, or undefined when the stream ended — which is a cancellation.
interface Reader {
line(options?: ReadOptions): Promise<string | undefined>;
}ReadOptions
interface ReadOptions {
/**
* Do not echo what is typed. Set for `password`, and honoured by whatever is reading —
* this module never sees a terminal, so it cannot hide anything itself, and a widget
* that never writes back what it read cannot leak it either.
*/
hidden?: boolean;
}Writer
interface Writer {
write(text: string): void;
/**
* How many columns the terminal behind this writer is, when it knows. Line mode never
* reads it; the raw renderer does, because a row wider than the terminal occupies more
* than one row of screen and the repaint has to climb all of them.
*/
readonly columns?: number | undefined;
}Types
Answer
type Answer = string | boolean | string[];Asked
Answered, or cancelled — cancellation is a value here and a CANCELLED error above (R4).
type Asked = {
ok: true;
value: Answer;
} | {
ok: false;
reason: 'cancelled';
};