Add help for positional arguments

This commit is contained in:
Jerko Steiner 2019-08-06 11:37:44 +07:00
parent a1ac8880d4
commit 87d515d89b
4 changed files with 63 additions and 19 deletions

View File

@ -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'))
})

View File

@ -51,9 +51,13 @@ const iterate = <T>(arr: T[]): IIterator<T> => {
}
}
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<T extends TArgTypeName>(

View File

@ -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])
}

View File

@ -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)
})
}