import { createHeadlessFormModel } from "../pi-tui/form-model.ts"; import { getTypedCommandRefinementIssues } from "../parser.ts"; import type { ArgumentDefinitions, ArgumentValue, FormMode, ParsedCommandArguments, } from "../types.ts"; import type { RegisteredTypedCommand } from "../pi/command-types.ts"; import { ArgumentFormComponent, type FormResult } from "./dense-component.ts"; import type { OpenArgumentFormOptions } from "./open.ts"; import type { ArgumentFormContext } from "./context.ts"; function signalAborted(signal?: AbortSignal): boolean { return signal?.aborted === true; } function resolveFormTitle( command: RegisteredTypedCommand, options: OpenArgumentFormOptions, ): string { if (options.title !== undefined) { return options.title; } const title = command.formTitle; if (title !== undefined) { if (typeof title === "string") { return title; } } return command.name.replace(" ", " › "); } /** Open the dense TUI argument form for a parsed typed command. */ export async function openDenseArgumentForm( command: RegisteredTypedCommand, parsed: ParsedCommandArguments, mode: FormMode, ctx: ArgumentFormContext, options: OpenArgumentFormOptions, ): Promise | undefined> { const { state, fields, initialSelection } = createHeadlessFormModel(command.args, parsed, mode); const appearance = options.appearance.form; if (fields.length === 0 && !signalAborted(options.signal)) { return state; } if (signalAborted(options.signal)) { return undefined; } let removeAbortListener = (): void => {}; let result: FormResult | undefined; try { result = await ctx.ui.custom((tui, theme, keybindings, done) => { const abort = (): void => { done(undefined); }; if (signalAborted(options.signal)) { done(undefined); } else { options.signal?.addEventListener("abort", abort, { once: true }); removeAbortListener = () => { options.signal?.removeEventListener("abort", abort); }; } return new ArgumentFormComponent( tui, resolveFormTitle(command, options), fields, state, theme, command.formSymbols, appearance, options.completionCapabilities, keybindings, (values) => getTypedCommandRefinementIssues(command, values, parsed.provided), done, initialSelection, ); }); } finally { removeAbortListener(); } if (signalAborted(options.signal) || result === undefined || !result.confirmed) { return undefined; } if (result.submitInput !== undefined) { options.onTuiSubmitInput?.(result.submitInput); } return result.state; }