From 87d515d89b43799fe893a5ebd08144811e3dcbef Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Tue, 6 Aug 2019 11:37:44 +0700 Subject: [PATCH] Add help for positional arguments --- packages/argparse/src/argparse.test.ts | 17 ++++++++++-- packages/argparse/src/argparse.ts | 25 +++++++++++++++-- packages/scripts/src/commands/build.ts | 38 ++++++++++++++++---------- packages/scripts/src/index.ts | 2 +- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/packages/argparse/src/argparse.test.ts b/packages/argparse/src/argparse.test.ts index a4f0076..11d7eec 100644 --- a/packages/argparse/src/argparse.test.ts +++ b/packages/argparse/src/argparse.test.ts @@ -220,6 +220,9 @@ describe('argparse', () => { three: arg('boolean'), }) expect(help()).toEqual([ + '[OPTIONS] ', + '', + 'Options:', ' --one string ', ' --two number ', ' --three boolean ', @@ -234,12 +237,22 @@ describe('argparse', () => { default: 'choice-1', alias: 'o', }), - two: arg('number'), + two: arg('number', { + positional: true, + required: true, + }), + three: arg('number', { + positional: true, + }), }) expect(help()).toEqual([ + '[OPTIONS] TWO [THREE]', + '', + 'Options:', '-o, --one string first argument ' + '(required, default: choice-1, choices: choice-1,choice-2)', - ' --two number ', + ' --two number (required)', + ' --three number ', ].join('\n')) }) diff --git a/packages/argparse/src/argparse.ts b/packages/argparse/src/argparse.ts index 0ad99cb..1682c8c 100644 --- a/packages/argparse/src/argparse.ts +++ b/packages/argparse/src/argparse.ts @@ -51,9 +51,13 @@ const iterate = (arr: T[]): IIterator => { } } +function createError(message: string) { + return new Error('Error parsing arguments: ' + message) +} + function assert(cond: boolean, message: string) { if (!cond) { - throw new Error('Error parsing arguments: ' + message) + throw createError(message) } } @@ -118,7 +122,20 @@ export function padRight(str: string, chars: number) { } export function help(config: IArgsConfig) { - return Object.keys(config).map(argument => { + const keys = Object.keys(config) + + const positionalHelp = [ + '[OPTIONS]', + keys + .filter(k => config[k].positional) + .map(k => config[k].required + ? `${k.toUpperCase()}` + : `[${k.toUpperCase()}]`, + ) + .join(' '), + ].join(' ') + + const argsHelp = 'Options:\n' + keys.map(argument => { const argConfig = config[argument] const {alias, type} = argConfig const name = alias @@ -140,6 +157,10 @@ export function help(config: IArgsConfig) { return padRight(name + ' ' + type, 30) + ' ' + description + sample }) .join('\n') + + return [positionalHelp, argsHelp] + .filter(h => h.length) + .join('\n\n') } export function arg( diff --git a/packages/scripts/src/commands/build.ts b/packages/scripts/src/commands/build.ts index cc2985b..fb70e98 100644 --- a/packages/scripts/src/commands/build.ts +++ b/packages/scripts/src/commands/build.ts @@ -1,6 +1,6 @@ import * as fs from 'fs' import * as p from 'path' -import {argparse} from '@rondo/argparse' +import {argparse, arg} from '@rondo/argparse' import {findNodeModules} from '../modules' import {join} from 'path' import {run} from '../run' @@ -8,22 +8,32 @@ import {run} from '../run' const tsc = 'ttsc' export async function build(...argv: string[]) { - const {esm, project, watch} = argparse({ - project: { - type: 'string', + const {parse, help} = argparse({ + project: arg('string', { alias: 'p', default: '.', - }, - esm: { - type: 'boolean', - }, - watch: { - type: 'boolean', + description: 'Project to build', + positional: true, + }), + esm: arg('boolean', { + description: 'Build project from tsconfig.esm.json', + }), + watch: arg('boolean', { alias: 'w', - }, - })(argv) - const path = esm ? join(project, 'tsconfig.esm.json') : project - const watchArgs = watch ? ['--watch', '--preserveWatchOutput'] : [] + description: 'Watch for changes', + }), + help: arg('boolean', { + alias: 'h', + description: 'Print help message', + }), + }) + const args = parse(argv) + if (args.help) { + console.log('Usage: rondo build ' + help()) + return + } + const path = args.esm ? join(args.project, 'tsconfig.esm.json') : args.project + const watchArgs = args.watch ? ['--watch', '--preserveWatchOutput'] : [] await run(tsc, ['--build', path, ...watchArgs]) } diff --git a/packages/scripts/src/index.ts b/packages/scripts/src/index.ts index 015e533..94e560e 100644 --- a/packages/scripts/src/index.ts +++ b/packages/scripts/src/index.ts @@ -17,7 +17,7 @@ async function run(...argv: string[]) { if (typeof require !== 'undefined' && require.main === module) { run(...process.argv.slice(2)) .catch(err => { - console.log('> ' + err.stack) + console.log('> ' + err.message) process.exit(1) }) }