9
9
10
10
namespace Toolkit \Cli ;
11
11
12
+ use Toolkit \Cli \Helper \FlagHelper ;
12
13
use Toolkit \Cli \Util \LineParser ;
13
14
use function array_flip ;
14
15
use function array_merge ;
15
16
use function current ;
16
17
use function escapeshellarg ;
17
18
use function explode ;
18
- use function is_bool ;
19
19
use function is_int ;
20
- use function is_numeric ;
21
20
use function next ;
22
21
use function preg_match ;
23
22
use function str_split ;
24
- use function stripos ;
25
23
use function strpos ;
26
24
use function substr ;
27
25
use function trim ;
33
31
*/
34
32
class Flags
35
33
{
36
- // These words will be as a Boolean value
37
- private const TRUE_WORDS = '|on|yes|true| ' ;
38
-
39
- private const FALSE_WORDS = '|off|no|false| ' ;
40
-
41
34
/**
42
35
* @param array $argv
43
36
*
@@ -134,26 +127,26 @@ public static function parseArgv(array $params, array $config = []): array
134
127
// Special short style
135
128
// posix: -abc will expand: -a -b -c
136
129
// unix: -abc will expand: -a=bc
137
- 'shortStyle ' => 'posix ' ,
130
+ 'shortStyle ' => 'posix ' ,
138
131
], $ config );
139
132
140
133
$ args = $ sOpts = $ lOpts = [];
141
134
// config
142
135
$ boolOpts = array_flip ((array )$ config ['boolOpts ' ]);
143
136
$ arrayOpts = array_flip ((array )$ config ['arrayOpts ' ]);
144
137
145
- // each() will deprecated at 7.2. so,there use current and next instead it.
146
- // while (list(,$p) = each($params)) {
138
+ $ optParseEnd = false ;
147
139
while (false !== ($ p = current ($ params ))) {
148
140
next ($ params );
149
141
150
- // empty string
151
- if ($ p === '' ) {
142
+ // option parse end, collect remaining arguments.
143
+ if ($ optParseEnd ) {
144
+ self ::collectArgs ($ args , $ p );
152
145
continue ;
153
146
}
154
147
155
148
// is options and not equals '-' '--'
156
- if ($ p [0 ] === '- ' && '' !== trim ($ p , '- ' )) {
149
+ if ($ p && $ p [0 ] === '- ' && '' !== trim ($ p , '- ' )) {
157
150
$ value = true ;
158
151
$ isLong = false ;
159
152
$ option = substr ($ p , 1 );
@@ -177,7 +170,7 @@ public static function parseArgv(array $params, array $config = []): array
177
170
$ nxt = current ($ params );
178
171
179
172
// next elem is value. fix: allow empty string ''
180
- if ($ value === true && !isset ($ boolOpts [$ option ]) && self :: nextIsValue ($ nxt )) {
173
+ if ($ value === true && !isset ($ boolOpts [$ option ]) && FlagHelper:: isOptionValue ($ nxt )) {
181
174
// list(,$val) = each($params);
182
175
$ value = $ nxt ;
183
176
next ($ params );
@@ -190,7 +183,7 @@ public static function parseArgv(array $params, array $config = []): array
190
183
continue ;
191
184
}
192
185
193
- $ value = self ::filterBool ($ value );
186
+ $ value = FlagHelper ::filterBool ($ value );
194
187
$ isArray = isset ($ arrayOpts [$ option ]);
195
188
196
189
if ($ isLong ) {
@@ -208,21 +201,16 @@ public static function parseArgv(array $params, array $config = []): array
208
201
continue ;
209
202
}
210
203
204
+ // stop parse options:
205
+ // - found '--' will stop parse options
206
+ if ($ p === '-- ' ) {
207
+ $ optParseEnd = true ;
208
+ continue ;
209
+ }
210
+
211
211
// parse arguments:
212
212
// - param doesn't belong to any option, define it is args
213
-
214
- // value specified inline (<arg>=<value>)
215
- if (strpos ($ p , '= ' ) !== false ) {
216
- [$ name , $ value ] = explode ('= ' , $ p , 2 );
217
-
218
- if (self ::isValidArgName ($ name )) {
219
- $ args [$ name ] = self ::filterBool ($ value );
220
- } else {
221
- $ args [] = $ p ;
222
- }
223
- } else {
224
- $ args [] = $ p ;
225
- }
213
+ self ::collectArgs ($ args , $ p );
226
214
}
227
215
228
216
if ($ config ['mergeOpts ' ]) {
@@ -232,6 +220,26 @@ public static function parseArgv(array $params, array $config = []): array
232
220
return [$ args , $ sOpts , $ lOpts ];
233
221
}
234
222
223
+ /**
224
+ * @param array $args
225
+ * @param string $p
226
+ */
227
+ private static function collectArgs (array &$ args , string $ p ): void
228
+ {
229
+ // value specified inline (<arg>=<value>)
230
+ if (strpos ($ p , '= ' ) !== false ) {
231
+ [$ name , $ value ] = explode ('= ' , $ p , 2 );
232
+
233
+ if (FlagHelper::isValidName ($ name )) {
234
+ $ args [$ name ] = FlagHelper::filterBool ($ value );
235
+ } else {
236
+ $ args [] = $ p ;
237
+ }
238
+ } else {
239
+ $ args [] = $ p ;
240
+ }
241
+ }
242
+
235
243
/**
236
244
* parse custom array params
237
245
* ```php
@@ -295,79 +303,6 @@ public static function parseString(string $string, array $config = []): array
295
303
return self ::parseArgv ($ flags , $ config );
296
304
}
297
305
298
- /**
299
- * @param string|bool $val
300
- * @param bool $enable
301
- *
302
- * @return bool|int|mixed
303
- */
304
- public static function filterBool ($ val , bool $ enable = true )
305
- {
306
- if ($ enable ) {
307
- if (is_bool ($ val ) || is_numeric ($ val )) {
308
- return $ val ;
309
- }
310
-
311
- // check it is a bool value.
312
- if (false !== stripos (self ::TRUE_WORDS , "| $ val| " )) {
313
- return true ;
314
- }
315
-
316
- if (false !== stripos (self ::FALSE_WORDS , "| $ val| " )) {
317
- return false ;
318
- }
319
- }
320
-
321
- return $ val ;
322
- }
323
-
324
- /**
325
- * check next is option value
326
- *
327
- * @param mixed $val
328
- *
329
- * @return bool
330
- */
331
- public static function nextIsValue ($ val ): bool
332
- {
333
- // current() fetch error, will return FALSE
334
- if ($ val === false ) {
335
- return false ;
336
- }
337
-
338
- // if is: '', 0
339
- if (!$ val ) {
340
- return true ;
341
- }
342
-
343
- // is not option name.
344
- if ($ val [0 ] !== '- ' ) {
345
- // ensure is option value.
346
- if (false === strpos ($ val , '= ' )) {
347
- return true ;
348
- }
349
-
350
- // is string value, but contains '='
351
- [$ name ,] = explode ('= ' , $ val , 2 );
352
-
353
- // named argument OR invlaid: 'some = string'
354
- return false === self ::isValidArgName ($ name );
355
- }
356
-
357
- // is option name.
358
- return false ;
359
- }
360
-
361
- /**
362
- * @param string $name
363
- *
364
- * @return bool
365
- */
366
- public static function isValidArgName (string $ name ): bool
367
- {
368
- return preg_match ('#^\w+$# ' , $ name ) === 1 ;
369
- }
370
-
371
306
/**
372
307
* Escapes a token through escapeshellarg if it contains unsafe chars.
373
308
*
0 commit comments