@@ -6,17 +6,12 @@ import type {
66 BooleanType ,
77 StringType ,
88 Collectable ,
9-
109 Aliases ,
1110} from "./types.js" ;
1211export { ParseOptions , Args } from "./types.js" ;
1312
14- const FLAG_RE = / (?: - - ? ( [ ^ \s = ] + ) ) (?: \s + | = | $ ) ( " [ ^ " ] + " | ' [ ^ ' ] + ' | [ ^ - \s ] + ) ? | \S + / gm;
1513const BOOL_RE = / ^ ( t r u e | f a l s e ) $ / ;
16- const NUMBER_RE = / ^ ( \. ? \d ) / ;
1714const QUOTED_RE = / ^ ( ' | " ) .* \1$ / ;
18- const NEGATED_RE = / ^ n o - / ;
19- const SINGLE_RE = / ^ - [ ^ - ] / ;
2015
2116const set = ( obj : NestedMapping , key : string , value : any , type ?: string ) => {
2217 if ( key . includes ( "." ) ) {
@@ -29,38 +24,44 @@ const set = (obj: NestedMapping, key: string, value: any, type?: string) => {
2924 }
3025 key = parts [ parts . length - 1 ] ;
3126 }
32- if ( type === ' array' && obj [ key ] !== undefined ) {
27+ if ( type === " array" && obj [ key ] !== undefined ) {
3328 if ( Array . isArray ( obj [ key ] ) ) {
3429 ( obj [ key ] as any [ ] ) . push ( value ) ;
3530 } else {
3631 obj [ key ] = [ obj [ key ] , value ] ;
3732 }
3833 } else {
39- obj [ key ] = type === ' array' ? [ value ] : value ;
34+ obj [ key ] = type === " array" ? [ value ] : value ;
4035 }
4136} ;
4237
43- const type = ( key : string , opts : Record < 'boolean' | 'string' | 'array' , string [ ] > ) : 'boolean' | 'string' | 'array' | undefined => {
44- for ( const [ t , keys ] of Object . entries ( opts ) ) {
45- if ( keys . includes ( key ) ) return t as keyof typeof opts ;
46- }
38+ const type = (
39+ key : string ,
40+ opts : Record < "boolean" | "string" | "array" , string [ ] >
41+ ) : "boolean" | "string" | "array" | undefined => {
42+ if ( opts . array && opts . array . length > 0 && opts . array . includes ( key ) )
43+ return "array" ;
44+ if ( opts . string && opts . string . length > 0 && opts . string . includes ( key ) )
45+ return "string" ;
46+ if ( opts . boolean && opts . boolean . length > 0 && opts . boolean . includes ( key ) )
47+ return "boolean" ;
4748 return ;
48- }
49+ } ;
4950
50- const defaultValue = ( type ?: ' boolean' | ' string' | ' array' ) => {
51- if ( type === ' string' ) return '' ;
52- if ( type === ' array' ) return [ ] ;
51+ const defaultValue = ( type ?: " boolean" | " string" | " array" ) => {
52+ if ( type === " string" ) return "" ;
53+ if ( type === " array" ) return [ ] ;
5354 return true ;
54- }
55+ } ;
5556
56- const coerce = ( value : string , type ?: ' string' | ' boolean' | "array" ) => {
57- if ( type === ' string' ) return value ;
58- if ( type === ' boolean' ) return ! ! value ;
57+ const coerce = ( value ? : string , type ?: " string" | " boolean" | "array" ) => {
58+ if ( type === " string" ) return value ;
59+ if ( type === " boolean" ) return ! ! value ;
5960
6061 if ( ! value ) return value ;
61- if ( BOOL_RE . test ( value ) ) return value === "true" ;
62- if ( NUMBER_RE . test ( value ) ) return Number ( value ) ;
63- if ( QUOTED_RE . test ( value ) ) return value . slice ( 1 , - 1 ) ;
62+ if ( value . length > 3 && BOOL_RE . test ( value ) ) return value === "true" ;
63+ if ( value . length > 2 && QUOTED_RE . test ( value ) ) return value . slice ( 1 , - 1 ) ;
64+ if ( value [ 0 ] === '.' && / \d / . test ( value [ 1 ] ) || / \d / . test ( value [ 0 ] ) ) return Number ( value ) ;
6465 return value ;
6566} ;
6667
@@ -82,48 +83,70 @@ export function parse<
8283 TAliasNames extends string = string
8384> (
8485 argv : string [ ] ,
85- { default : defaults , alias : aliases = { } , ...types } : ParseOptions <
86- TBooleans ,
87- TStrings ,
88- TCollectable ,
89- TDefaults ,
90- TAliases
91- > = { }
86+ {
87+ default : defaults ,
88+ alias : aliases ,
89+ ...types
90+ } : ParseOptions < TBooleans , TStrings , TCollectable , TDefaults , TAliases > = { }
9291) : Args < TArgs > {
9392 if ( argv . length === 0 ) return { } as Args < TArgs > ;
94- const str = argv . join ( ' ' ) ;
95-
96- FLAG_RE . lastIndex = 0 ;
97- let m ;
9893 const obj = { ...defaults , _ : [ ] } as unknown as Args < TArgs > ;
99- while ( ( m = FLAG_RE . exec ( str ) ) ) {
100- let [ value , key , arg ] = m ;
101- let isAliased = false ;
102- if ( ! key && ! arg ) {
103- ( obj as any ) . _ . push ( coerce ( value ) ) ;
104- continue ;
105- }
106- if ( aliases . hasOwnProperty ( key ) ) {
107- key = aliases [ key as keyof typeof aliases ] as string ;
108- isAliased = true ;
109- }
110- const t = type ( key , types as any ) ;
11194
112- if ( ! isAliased && SINGLE_RE . test ( value ) ) {
113- // Special case! `-a.a1` should be treated as { a: '.a1' }
114- if ( key . includes ( "." ) ) {
115- set ( obj , key . split ( "." ) [ 0 ] , "." + key . split ( "." ) . slice ( 1 ) . join ( "." ) ) ;
116- FLAG_RE . lastIndex -= arg ?. length ?? 0 ;
95+ const args = [ ] ;
96+ for ( let i = 0 ; i < argv . length ; i ++ ) {
97+ const curr = argv [ i ] ;
98+ const next = argv [ i + 1 ] ;
99+
100+ let t : 'string' | 'boolean' | 'array' | undefined ;
101+ let key = '' ;
102+ let value : string | undefined ;
103+
104+ if ( curr . length > 1 && curr [ 0 ] === "-" ) {
105+ if ( curr [ 1 ] !== "-" && curr . length > 2 && ! curr . includes ( '=' ) ) {
106+ if ( curr . includes ( '.' ) ) {
107+ key = curr . slice ( 1 , 2 ) ;
108+ value = curr . slice ( 2 ) ;
109+ } else {
110+ const keys = curr . slice ( 1 , - 1 ) ;
111+ for ( let key of keys ) {
112+ if ( aliases && ( aliases as Record < string , any > ) [ key ] !== undefined ) {
113+ key = aliases [ key as keyof typeof aliases ] as string ;
114+ }
115+ set ( obj , key , defaultValue ( t ) , t )
116+ }
117+ key = curr . slice ( - 1 )
118+ if ( next && next [ 0 ] !== '-' ) {
119+ value = next ;
120+ i ++ ;
121+ }
122+ }
123+ } else if ( ! curr . includes ( "=" ) && next && next [ 0 ] !== "-" ) {
124+ key = curr . replace ( / ^ - { 1 , 2 } / , '' ) ;
125+ value = next ;
126+ t = type ( key , types as any ) ;
127+ i ++ ;
117128 } else {
118- for ( const k of key . slice ( 0 , - 1 ) ) {
119- set ( obj , k , true ) ;
129+ const eq = curr . indexOf ( '=' ) ;
130+ if ( eq === - 1 ) {
131+ key = curr . replace ( / ^ - { 1 , 2 } / , '' ) ;
132+ } else {
133+ key = curr . slice ( 0 , eq ) . replace ( / ^ - { 1 , 2 } / , '' ) ;
134+ value = curr . slice ( eq + 1 ) ;
120135 }
121- set ( obj , key [ key . length - 1 ] , coerce ( arg , t ) ?? true ) ;
136+ t = type ( key , types as any ) ;
122137 }
123- } else if ( ( ! t || t === 'boolean' ) && NEGATED_RE . test ( key ) ) {
124- set ( obj , key . slice ( 3 ) , false ) ;
125- } else {
126- set ( obj , key , coerce ( arg , t ) ?? defaultValue ( t ) , t ) ;
138+
139+ if ( ( ! t || t === "boolean" ) && key . length > 3 && key . startsWith ( 'no-' ) ) {
140+ set ( obj , key . slice ( 3 ) , false )
141+ } else {
142+ if ( aliases && ( aliases as Record < string , any > ) [ key ] !== undefined ) {
143+ key = aliases [ key as keyof typeof aliases ] as string ;
144+ }
145+ set ( obj , key , coerce ( value , t ) ?? defaultValue ( t ) , t )
146+ }
147+ } else if ( curr ) {
148+ ( obj as any ) . _ . push ( coerce ( curr ) ) ;
149+ continue ;
127150 }
128151 }
129152
0 commit comments