import { ArgParser, ParsingResult, ParseContext } from './argparser.ts'; import { OutputOf } from './from.ts'; import { PositionalArgument } from './newparser/parser.ts'; import { ProvidesHelp, Descriptive, Displayed } from './helpdoc.ts'; import { Type, HasType } from './type.ts'; import * as Result from './Result.ts'; import { string } from './types.ts'; type PositionalConfig> = HasType & Partial; type PositionalParser> = ArgParser< OutputOf > & ProvidesHelp & Partial; function fullPositional>( config: PositionalConfig ): PositionalParser { const displayName = config.displayName ?? config.type.displayName ?? 'arg'; return { description: config.description ?? config.type.description, helpTopics() { return [ { category: 'arguments', usage: `<${displayName}>`, description: config.description ?? config.type.description ?? 'self explanatory', defaults: [], }, ]; }, register(_opts) {}, async parse({ nodes, visitedNodes, }: ParseContext): Promise>> { const positionals = nodes.filter( (node): node is PositionalArgument => node.type === 'positionalArgument' && !visitedNodes.has(node) ); const positional = positionals[0]; if (!positional) { return Result.err({ errors: [ { nodes: [], message: `No value provided for ${displayName}`, }, ], }); } visitedNodes.add(positional); const decoded = await Result.safeAsync(config.type.from(positional.raw)); if (Result.isErr(decoded)) { return Result.err({ errors: [ { nodes: [positional], message: decoded.error.message, }, ], }); } return Result.ok(decoded.value); }, }; } type StringType = Type; /** * A positional command line argument. * * Decodes one argument that is not a flag or an option: * In `hello --key value world` we have 2 positional arguments — `hello` and `world`. * * @param config positional argument config */ export function positional>( config: HasType & Partial ): PositionalParser; export function positional( config?: Partial & Displayed & Descriptive> ): PositionalParser; export function positional( config?: Partial> & Partial ): PositionalParser { return fullPositional({ type: string, ...config, }); }