caique
API reference

caique/editor

Every export of caique/editor, with its signature and doc comment: editor, submissions, EDITOR_KEYS, plus 8 types.

import { editor, submissions, EDITOR_KEYS } from 'caique/editor';

Functions

editor

Build an editor.

onKey never reads a stream and never waits: it is called with a key, returns a state, and says when the entry was submitted or cancelled. render is the frame for a state.

function editor(options?: EditorOptions): Editor;
ParameterType
options (optional)EditorOptions

Returns Editor

submissions

The editor's entries when there is no terminal to edit on: one per line of input, ending when the input does. A pipe, a file and /dev/null all end — so this never waits for a key that cannot come (controlroom R7).

function submissions(input: NodeJS.ReadableStream): AsyncGenerator<string, void, undefined>;
ParameterType
inputNodeJS.ReadableStream

Returns AsyncGenerator<string, void, undefined>

Constants

EDITOR_KEYS

The editor's commands, as data. A host passes its own keymap to change them.

const EDITOR_KEYS: {
    readonly enter: "submit";
    readonly 'meta+enter': "newline";
    readonly 'ctrl+j': "newline";
    readonly up: "previous";
    readonly down: "next";
    readonly tab: "complete";
    readonly escape: "dismiss";
    readonly 'ctrl+c': "cancel";
};

Interfaces

Editor

An editor: its first state, its reducer, and its drawing. All three are pure.

interface Editor {
    initial: EditorState;
    onKey: (state: EditorState, key: KeyPress) => Step;
    render: (state: EditorState) => Frame;
}

EditorOptions

interface EditorOptions {
    /** The entry the editor opens with. */
    text?: string;
    /** Earlier entries, oldest first: what Up recalls. */
    history?: readonly string[];
    /**
     * Candidates for the word before the cursor (`/com`, `@fi`); an empty list shows no menu.
     * The program decides what a word means — the editor only asks.
     */
    complete?: (word: string) => readonly string[];
    /** Replaces `EDITOR_KEYS`. Any key it does not bind is typed, if it is text. */
    keymap?: Keymap<EditorAction>;
    /** Drawn before the first row; the rows under it are indented to match. */
    prompt?: string;
}

EditorState

Everything the editor is. Plain data: no functions, nothing a host cannot copy or log.

interface EditorState {
    /** The entry being written; `\n` separates its rows. */
    readonly text: string;
    /** Where the cursor is in `text`, in UTF-16 units. */
    readonly cursor: number;
    /** Earlier entries, oldest first. */
    readonly history: readonly string[];
    /** Which history entry is shown; `history.length` is the entry being written. */
    readonly at: number;
    /** The entry being written, kept while the history is browsed. */
    readonly draft: string;
    /** A bracketed paste being collected, or `undefined` outside one. */
    readonly paste: string | undefined;
    readonly menu: Menu | undefined;
    /** The word whose menu Escape closed: it stays closed until the word changes. */
    readonly dismissed: string | undefined;
}

Frame

Where the editor sits on screen once rendered: its rows, and the cursor among them.

interface Frame {
    lines: string[];
    /** Row and display column of the cursor within `lines`, before any wrapping by the host. */
    cursor: {
        row: number;
        column: number;
    };
}

The completion menu: what the program offered for the word before the cursor.

interface Menu {
    word: string;
    items: readonly string[];
    selected: number;
}

Step

One key's result: the next state, and an event when the key ended the entry.

interface Step {
    state: EditorState;
    event?: EditorEvent;
}

Types

EditorAction

What a key can ask the editor to do, beyond typing.

type EditorAction = 'submit' | 'newline' | 'previous' | 'next' | 'complete' | 'dismiss' | 'cancel';

EditorEvent

What a key did that the host has to act on.

type EditorEvent = {
    type: 'submit';
    text: string;
} | {
    type: 'cancel';
};

On this page