diff --git a/src/lib/options.ts b/src/lib/options.ts index e1fddf7..410d14b 100644 --- a/src/lib/options.ts +++ b/src/lib/options.ts @@ -4,12 +4,12 @@ export type Options = Record & { $min?: number; $max?: number; }; -type ParsedOptions

= { +type ParsedOptions

= { [K in keyof P]: K extends "$min" | "$max" ? never : P[K] extends 0 ? boolean - : string[] | []; + : V[] | []; } & { error?: string; }; @@ -17,44 +17,69 @@ type ParsedOptions

= { export function getOpt

( argv: TextPiece[], options: P, - procBody: (switches: ParsedOptions

, ...argv: string[]) => ProcResult + procBody: ( + switches: ParsedOptions, + ...argv: string[] + ) => ProcResult ): ProcResult; export function getOpt

( argv: TextPiece[], options: P -): [ParsedOptions

, ...string[]]; +): [ParsedOptions, ...string[]]; export function getOpt

( argv: TextPiece[], options: P, - procBody?: (switches: ParsedOptions

, ...argv: string[]) => ProcResult -): [ParsedOptions

, ...string[]] | ProcResult { + procBody?: ( + switches: ParsedOptions, + ...argv: string[] + ) => ProcResult +): [ParsedOptions, ...string[]] | ProcResult { const [flags, textPieces] = getOptCore(argv, options); - if (procBody) { - if ("error" in flags) { + if ("error" in flags) { + if (procBody) { return flags as ErrorResult; } else { - return procBody(flags, ...textPieces.map(AsText)); + return [flags as ParsedOptions]; } + } + + const simpleFlags = Object.fromEntries( + Object.entries(flags).map(([name, textPieces]) => [ + name, + typeof textPieces == "boolean" + ? textPieces + : (textPieces as TextPiece[]).map(AsText), + ]) + ) as ParsedOptions; + + if (procBody) { + return procBody(simpleFlags, ...textPieces.map(AsText)); } else { - return [flags, ...textPieces.map(AsText)]; + return [simpleFlags, ...textPieces.map(AsText)]; } } export function getOptRaw

( argv: TextPiece[], options: P, - procBody: (switches: ParsedOptions

, argv: TextPiece[]) => ProcResult + procBody: ( + switches: ParsedOptions, + argv: TextPiece[] + ) => ProcResult ): ProcResult; export function getOptRaw

( argv: TextPiece[], options: P -): [ParsedOptions

, TextPiece[]]; +): [ParsedOptions, TextPiece[]]; export function getOptRaw

( argv: TextPiece[], options: P, - procBody?: (switches: ParsedOptions

, argv: TextPiece[]) => ProcResult -): [ParsedOptions

, TextPiece[]] | ProcResult { + procBody?: ( + switches: ParsedOptions, + argv: TextPiece[] + ) => ProcResult +): [ParsedOptions, TextPiece[]] | ProcResult { const [flags, textPieces] = getOptCore(argv, options); if (procBody) { @@ -73,14 +98,14 @@ const SWITCH_REGEX = /^-([^]*)/; function getOptCore

( argv: TextPiece[], options: P -): [ParsedOptions

, TextPiece[]] { +): [ParsedOptions, TextPiece[]] { const [cmd, ...textPieces] = argv; const positionalArgs: TextPiece[] = []; - const flags: ParsedOptions

= Object.fromEntries( + const flags: ParsedOptions = Object.fromEntries( Object.entries(options) .filter(([name]) => name != "$min" && name != "$max") .map(([name]) => [name, options[name] == 0 ? false : []]) - ) as ParsedOptions

; + ) as ParsedOptions; // loop over args & extract switches for (let i = 0; i < textPieces.length; i++) { @@ -96,14 +121,15 @@ function getOptCore

( continue; } - const switchName = switchMatch[1] as keyof ParsedOptions

& string; + const switchName = switchMatch[1] as keyof ParsedOptions & + string; if (!(switchName in flags)) { return [ { error: `${AsText( cmd )}: -${switchName} is not a switch this command knows about`, - } as ParsedOptions

, + } as ParsedOptions, [], ]; } @@ -115,13 +141,13 @@ function getOptCore

( return [ { error: `${AsText(cmd)}: Not enough arguments to -${switchName}`, - } as ParsedOptions

, + } as ParsedOptions, [], ]; } else { const takeUntil = i + switchArgCount; for (i++; i <= takeUntil; i++) { - (flags[switchName] as string[]).push(AsText(textPieces[i])); + (flags[switchName] as TextPiece[]).push(textPieces[i]); } } } @@ -131,7 +157,7 @@ function getOptCore

( return [ { error: `${AsText(cmd)}: Not enough arguments`, - } as ParsedOptions

, + } as ParsedOptions, [], ]; } @@ -139,7 +165,7 @@ function getOptCore

( return [ { error: `${AsText(cmd)}: Too many arguments`, - } as ParsedOptions

, + } as ParsedOptions, [], ]; }