import { UnionToIntersection, TupleTypes } from "./flag"; type Argument = ( v: string[] ) => { [key in N]: { value: T; position: number[]; usage: string } }; type StringArgument = Argument; type BooleanArgument = Argument; type NumberArgument = Argument; export type ArgumentOption = { usage?: string; }; export function makeStringArgument( name: N, opts: ArgumentOption = {} ): StringArgument { return (values: string[]) => { let value = ""; let i; for (i = 0; i < values.length; i++) { if (values[i]) { value = values[i]; break; } } if (value === "") { return { [name]: { value: undefined, ...opts, position: [] } }; } return { [name]: { value, ...opts, position: [i] } }; }; } export function makeBooleanArgument( name: N, opts: ArgumentOption = {} ): BooleanArgument { return (values: string[]) => { let value = ""; let i; for (i = 0; i < values.length; i++) { if (values[i]) { value = values[i]; break; } } if (value === "true") { return { [name]: { value: true, ...opts, position: [i] } }; } else if (value === "false") { return { [name]: { value: false, ...opts, position: [i] } }; } return { [name]: { value: undefined, ...opts, position: [] } }; }; } export function makeNumberArgument( name: N, opts: ArgumentOption = {} ): NumberArgument { return (values: string[]) => { let value = ""; let i; for (i = 0; i < values.length; i++) { if (values[i]) { value = values[i]; break; } } const v = parseInt(value, 10); return { [name]: { value: isNaN(v) ? undefined : v, ...opts, position: [i] } }; }; } export function makePositionalArguments< T extends Array<(args: string[]) => { [key: string]: any }> >(...argParsers: T): (args: string[]) => UnionToIntersection> { return (args: Array) => { const parsers = [...argParsers]; const validArgLength = args.filter(a => a).length; if (validArgLength < parsers.length) { return parsers.reduce((m, parser, idx) => { const res = parser([]); const v = Object.keys(res).reduce((m, k) => { return { ...m, ...res, [k]: { ...res[k], position: [idx] } }; }, {}); return { ...v, ...m }; }, {}); } const rest = [...args]; return args.reduce((m, arg) => { if (!arg) { return m; } if (parsers.length === 0) { return m; } const parser = parsers[0]; parsers.shift(); const res = parser(rest); const v = Object.keys(res).reduce((m, k) => { res[k].position.forEach(r => { rest[r] = undefined; }); return { ...m, ...res, [k]: { ...res[k] } }; }, {}); return { ...v, ...m }; }, {}); }; }