import { PrintHelp, Versioned } from './helpdoc.ts'; import { ParseContext, ParsingResult, Register } from './argparser.ts'; import { tokenize } from './newparser/tokenizer.ts'; import { parse } from './newparser/parser.ts'; import { errorBox } from './errorBox.ts'; import { err, ok, Result, isErr } from './Result.ts'; import { Exit } from './effects.ts'; export type Handling = { handler: (values: Values) => Result }; export type Runner = PrintHelp & Partial & Register & Handling & { run(context: ParseContext): Promise>; }; export type Into> = R extends Runner ? X : never; export async function run>( ap: R, strings: string[] ): Promise> { const result = await runSafely(ap, strings); if (isErr(result)) { return result.error.run(); } else { return result.value; } } /** * Runs a command but does not apply any effect */ export async function runSafely>( ap: R, strings: string[] ): Promise>> { const longOptionKeys = new Set(); const shortOptionKeys = new Set(); const hotPath: string[] = []; ap.register({ forceFlagShortNames: shortOptionKeys, forceFlagLongNames: longOptionKeys, }); const tokens = tokenize(strings); const nodes = parse(tokens, { longFlagKeys: longOptionKeys, shortFlagKeys: shortOptionKeys, }); try { const result = await ap.run({ nodes, visitedNodes: new Set(), hotPath }); if (isErr(result)) { throw new Exit({ message: errorBox(nodes, result.error.errors, hotPath), exitCode: 1, into: 'stderr', }); } else { return ok(result.value); } } catch (e) { if (e instanceof Exit) { return err(e); } throw e; } } /** * Run a command but don't quit. Returns an `Result` instead. */ export async function dryRun>( ap: R, strings: string[] ): Promise>> { const result = await runSafely(ap, strings); if (isErr(result)) { return err(result.error.dryRun()); } else { return result; } }