# caique/ask

> Every export of caique/ask, with its signature and doc comment: ask, projection, plus 6 types.

Source: https://caique.interlace.tools/docs/api/ask

<!-- Generated by scripts/api-reference.ts from the built dist/*.d.ts. Do not edit; run `npx tsx scripts/api-reference.ts`. -->

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.

```ts
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.

```ts
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.

```ts
function projection(spec: PromptSpec): string;
```

| Parameter | Type |
| :-- | :-- |
| `spec` | `PromptSpec` |

**Returns** `string`

## Interfaces

### Io

```ts
interface Io {
    reader: Reader;
    writer: Writer;
}
```

### Reader

A line of input, or `undefined` when the stream ended — which is a cancellation.

```ts
interface Reader {
    line(options?: ReadOptions): Promise<string | undefined>;
}
```

### ReadOptions

```ts
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

```ts
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

```ts
type Answer = string | boolean | string[];
```

### Asked

Answered, or cancelled — cancellation is a value here and a `CANCELLED` error above (R4).

```ts
type Asked = {
    ok: true;
    value: Answer;
} | {
    ok: false;
    reason: 'cancelled';
};
```
