import type { AnyStep, Input, Parser } from "./types.ts"; import { object } from "./object.ts"; import { format, inspect } from "./help.ts"; import { assert } from "@std/assert"; export interface Program

> { name: string; version?: string; config: P; createParser(input: Input): { type: "help"; print(): string; } | { type: "version"; print(): string; } | { type: "main"; parse(): ReturnType; }; } export function program

>( opts: { name: string; version?: string; config: P; }, ): Program

{ let { name, version, config } = opts; return { name, version, config, createParser(input: Input): ReturnType["createParser"]> { const preamble = object({ help: { description: "show help", aliases: ["-h"], }, ...(version ? { version: { description: "show version", aliases: ["-v"], }, } : {}), }); let probe = preamble.parse(input); assert(probe.ok); if (probe.value.help) { return { type: "help", print: () => printHelp(name, config, preamble) }; } if ((probe.value as { version?: boolean }).version) { return { type: "version", print: () => version!, }; } return { type: "main", parse: () => config.parse(probe.remainder), // deno-lint-ignore no-explicit-any } as any; }, }; } // --- internal --- function printHelp( name: string, config: Parser, preamble: Parser, ): string { let info = inspect(config); let extra = inspect(preamble); for (let opt of extra.opts) { info.opts.push(opt); } return format(info, name); }