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;| Parameter | Type |
|---|---|
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>;| Parameter | Type |
|---|---|
input | NodeJS.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;
};
}Menu
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';
};