@@ -220,6 +220,28 @@ const getFileName = (input) => {
220220 const m = / ( [ ^ \\ \/ ] + ) $ / . exec ( input ) ;
221221 return m ? m [ 1 ] : '' ;
222222} ;
223+ const camelcaseOptionName = ( name ) => {
224+ // Camelcase the option name
225+ // Don't camelcase anything after the dot `.`
226+ return name
227+ . split ( '.' )
228+ . map ( ( v , i ) => {
229+ return i === 0 ? camelcase ( v ) : v ;
230+ } )
231+ . join ( '.' ) ;
232+ } ;
233+ class CACError extends Error {
234+ constructor ( message ) {
235+ super ( message ) ;
236+ this . name = this . constructor . name ;
237+ if ( typeof Error . captureStackTrace === 'function' ) {
238+ Error . captureStackTrace ( this , this . constructor ) ;
239+ }
240+ else {
241+ this . stack = new Error ( message ) . stack ;
242+ }
243+ }
244+ }
223245
224246class Option {
225247 constructor ( rawName , description , config ) {
@@ -237,10 +259,10 @@ class Option {
237259 this . negated = true ;
238260 name = name . replace ( / ^ n o - / , '' ) ;
239261 }
240- return name ;
262+ return camelcaseOptionName ( name ) ;
241263 } )
242264 . sort ( ( a , b ) => ( a . length > b . length ? 1 : - 1 ) ) ; // Sort names
243- // Use the longese name (last one) as actual option name
265+ // Use the longest name (last one) as actual option name
244266 this . name = this . names [ this . names . length - 1 ] ;
245267 if ( this . negated ) {
246268 this . config . default = true ;
@@ -259,12 +281,9 @@ class Option {
259281}
260282
261283const deno = typeof window !== 'undefined' && window . Deno ;
262- const exit = ( code ) => {
263- return deno ? Deno . exit ( code ) : process . exit ( code ) ;
264- } ;
265284const processArgs = deno ? [ 'deno' ] . concat ( Deno . args ) : process . argv ;
266285const platformInfo = deno
267- ? `${ Deno . platform . os } -${ Deno . platform . arch } deno-${ Deno . version . deno } `
286+ ? `${ Deno . build . os } -${ Deno . build . arch } deno-${ Deno . version . deno } `
268287 : `${ process . platform } -${ process . arch } node-${ process . version } ` ;
269288
270289class Command {
@@ -411,21 +430,18 @@ class Command {
411430 : section . body ;
412431 } )
413432 . join ( '\n\n' ) ) ;
414- exit ( 0 ) ;
415433 }
416434 outputVersion ( ) {
417435 const { name } = this . cli ;
418436 const { versionNumber } = this . cli . globalCommand ;
419437 if ( versionNumber ) {
420438 console . log ( `${ name } /${ versionNumber } ${ platformInfo } ` ) ;
421439 }
422- exit ( 0 ) ;
423440 }
424441 checkRequiredArgs ( ) {
425442 const minimalArgsCount = this . args . filter ( arg => arg . required ) . length ;
426443 if ( this . cli . args . length < minimalArgsCount ) {
427- console . error ( `error: missing required args for command \`${ this . rawName } \`` ) ;
428- exit ( 1 ) ;
444+ throw new CACError ( `missing required args for command \`${ this . rawName } \`` ) ;
429445 }
430446 }
431447 /**
@@ -434,14 +450,13 @@ class Command {
434450 * Exit and output error when true
435451 */
436452 checkUnknownOptions ( ) {
437- const { rawOptions , globalCommand } = this . cli ;
453+ const { options , globalCommand } = this . cli ;
438454 if ( ! this . config . allowUnknownOptions ) {
439- for ( const name of Object . keys ( rawOptions ) ) {
455+ for ( const name of Object . keys ( options ) ) {
440456 if ( name !== '--' &&
441457 ! this . hasOption ( name ) &&
442458 ! globalCommand . hasOption ( name ) ) {
443- console . error ( `error: Unknown option \`${ name . length > 1 ? `--${ name } ` : `-${ name } ` } \`` ) ;
444- exit ( 1 ) ;
459+ throw new CACError ( `Unknown option \`${ name . length > 1 ? `--${ name } ` : `-${ name } ` } \`` ) ;
445460 }
446461 }
447462 }
@@ -450,16 +465,15 @@ class Command {
450465 * Check if the required string-type options exist
451466 */
452467 checkOptionValue ( ) {
453- const { rawOptions , globalCommand } = this . cli ;
468+ const { options : parsedOptions , globalCommand } = this . cli ;
454469 const options = [ ...globalCommand . options , ...this . options ] ;
455470 for ( const option of options ) {
456- const value = rawOptions [ option . name . split ( '.' ) [ 0 ] ] ;
471+ const value = parsedOptions [ option . name . split ( '.' ) [ 0 ] ] ;
457472 // Check required option value
458473 if ( option . required ) {
459474 const hasNegated = options . some ( o => o . negated && o . names . includes ( option . name ) ) ;
460475 if ( value === true || ( value === false && ! hasNegated ) ) {
461- console . error ( `error: option \`${ option . rawName } \` value is missing` ) ;
462- exit ( 1 ) ;
476+ throw new CACError ( `option \`${ option . rawName } \` value is missing` ) ;
463477 }
464478 }
465479 }
@@ -542,7 +556,6 @@ class CAC extends events.EventEmitter {
542556 * When a sub-command is matched, output the help message for the command
543557 * Otherwise output the global one.
544558 *
545- * This will also call `process.exit(0)` to quit the process.
546559 */
547560 outputHelp ( ) {
548561 if ( this . matchedCommand ) {
@@ -555,15 +568,13 @@ class CAC extends events.EventEmitter {
555568 /**
556569 * Output the version number.
557570 *
558- * This will also call `process.exit(0)` to quit the process.
559571 */
560572 outputVersion ( ) {
561573 this . globalCommand . outputVersion ( ) ;
562574 }
563- setParsedInfo ( { args, options, rawOptions } , matchedCommand , matchedCommandName ) {
575+ setParsedInfo ( { args, options } , matchedCommand , matchedCommandName ) {
564576 this . args = args ;
565577 this . options = options ;
566- this . rawOptions = rawOptions ;
567578 if ( matchedCommand ) {
568579 this . matchedCommand = matchedCommand ;
569580 }
@@ -585,11 +596,11 @@ class CAC extends events.EventEmitter {
585596 let shouldParse = true ;
586597 // Search sub-commands
587598 for ( const command of this . commands ) {
588- const mriResult = this . mri ( argv . slice ( 2 ) , command ) ;
589- const commandName = mriResult . args [ 0 ] ;
599+ const parsed = this . mri ( argv . slice ( 2 ) , command ) ;
600+ const commandName = parsed . args [ 0 ] ;
590601 if ( command . isMatched ( commandName ) ) {
591602 shouldParse = false ;
592- const parsedInfo = Object . assign ( { } , mriResult , { args : mriResult . args . slice ( 1 ) } ) ;
603+ const parsedInfo = Object . assign ( { } , parsed , { args : parsed . args . slice ( 1 ) } ) ;
593604 this . setParsedInfo ( parsedInfo , command , commandName ) ;
594605 this . emit ( `command:${ commandName } ` , command ) ;
595606 }
@@ -599,15 +610,15 @@ class CAC extends events.EventEmitter {
599610 for ( const command of this . commands ) {
600611 if ( command . name === '' ) {
601612 shouldParse = false ;
602- const mriResult = this . mri ( argv . slice ( 2 ) , command ) ;
603- this . setParsedInfo ( mriResult , command ) ;
613+ const parsed = this . mri ( argv . slice ( 2 ) , command ) ;
614+ this . setParsedInfo ( parsed , command ) ;
604615 this . emit ( `command:!` , command ) ;
605616 }
606617 }
607618 }
608619 if ( shouldParse ) {
609- const mriResult = this . mri ( argv . slice ( 2 ) ) ;
610- this . setParsedInfo ( mriResult ) ;
620+ const parsed = this . mri ( argv . slice ( 2 ) ) ;
621+ this . setParsedInfo ( parsed ) ;
611622 }
612623 if ( this . options . help && this . showHelpOnExit ) {
613624 this . outputHelp ( ) ;
@@ -639,7 +650,10 @@ class CAC extends events.EventEmitter {
639650 argsAfterDoubleDashes = argv . slice ( doubleDashesIndex + 1 ) ;
640651 argv = argv . slice ( 0 , doubleDashesIndex ) ;
641652 }
642- const parsed = lib ( argv , mriOptions ) ;
653+ let parsed = lib ( argv , mriOptions ) ;
654+ parsed = Object . keys ( parsed ) . reduce ( ( res , name ) => {
655+ return Object . assign ( { } , res , { [ camelcaseOptionName ( name ) ] : parsed [ name ] } ) ;
656+ } , { _ : [ ] } ) ;
643657 const args = parsed . _ ;
644658 delete parsed . _ ;
645659 const options = {
@@ -666,18 +680,15 @@ class CAC extends events.EventEmitter {
666680 }
667681 }
668682 }
669- // Camelcase option names and set dot nested option values
683+ // Set dot nested option values
670684 for ( const key of Object . keys ( parsed ) ) {
671- const keys = key . split ( '.' ) . map ( ( v , i ) => {
672- return i === 0 ? camelcase ( v ) : v ;
673- } ) ;
685+ const keys = key . split ( '.' ) ;
674686 setDotProp ( options , keys , parsed [ key ] ) ;
675687 setByType ( options , transforms ) ;
676688 }
677689 return {
678690 args,
679- options,
680- rawOptions : parsed
691+ options
681692 } ;
682693 }
683694 runMatchedCommand ( ) {
0 commit comments