89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
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<Values, Result> = { handler: (values: Values) => Result };
|
|
|
|
export type Runner<HandlerArgs, HandlerResult> = PrintHelp &
|
|
Partial<Versioned> &
|
|
Register &
|
|
Handling<HandlerArgs, HandlerResult> & {
|
|
run(context: ParseContext): Promise<ParsingResult<HandlerResult>>;
|
|
};
|
|
|
|
export type Into<R extends Runner<any, any>> = R extends Runner<any, infer X>
|
|
? X
|
|
: never;
|
|
|
|
export async function run<R extends Runner<any, any>>(
|
|
ap: R,
|
|
strings: string[]
|
|
): Promise<Into<R>> {
|
|
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<R extends Runner<any, any>>(
|
|
ap: R,
|
|
strings: string[]
|
|
): Promise<Result<Exit, Into<R>>> {
|
|
const longOptionKeys = new Set<string>();
|
|
const shortOptionKeys = new Set<string>();
|
|
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<R extends Runner<any, any>>(
|
|
ap: R,
|
|
strings: string[]
|
|
): Promise<Result<string, Into<R>>> {
|
|
const result = await runSafely(ap, strings);
|
|
if (isErr(result)) {
|
|
return err(result.error.dryRun());
|
|
} else {
|
|
return result;
|
|
}
|
|
}
|