@@ -270,18 +270,20 @@ class cmdline_processor
270
270
};
271
271
std::vector<arg> args;
272
272
273
- using callback = void (*)();
273
+ using callback0 = void (*)();
274
+ using callback1 = void (*)(std::string const &);
274
275
struct flag
275
276
{
276
277
int group = 0 ;
277
278
std::string name;
278
279
int unique_prefix = 0 ;
279
280
std::string description;
280
- callback handler;
281
+ callback0 handler0;
282
+ callback1 handler1;
281
283
std::string synonym;
282
284
283
- flag (int g, std::string_view n, std::string_view d, callback h , std::string_view s)
284
- : group{g}, name{n}, description{d}, handler{h }, synonym{s}
285
+ flag (int g, std::string_view n, std::string_view d, callback0 h0, callback1 h1 , std::string_view s)
286
+ : group{g}, name{n}, description{d}, handler0{h0}, handler1{h1 }, synonym{s}
285
287
{ }
286
288
};
287
289
std::vector<flag> flags;
@@ -315,42 +317,59 @@ class cmdline_processor
315
317
}
316
318
317
319
// Look for matches
318
- for (auto & arg : args)
320
+ for (auto arg = args. begin (); arg != args. end (); ++arg )
319
321
{
320
322
// The arg should never be empty, but we're going to do a [0]
321
323
// subscript next so we should either check or assert
322
- if (arg. text .empty ()) {
324
+ if (arg-> text .empty ()) {
323
325
continue ;
324
326
}
325
327
326
328
// Provide a way to ignore the rest of the command line
327
329
// for the purpose of looking for switches
328
- if (arg. text == " --" ) {
329
- arg. pos = processed;
330
+ if (arg-> text == " --" ) {
331
+ arg-> pos = processed;
330
332
break ;
331
333
}
332
334
333
335
for (auto & flag : flags) {
334
- auto length_to_match = std::max (flag.unique_prefix , as<int >(arg. text .length ())-1 );
336
+ auto length_to_match = std::max (flag.unique_prefix , as<int >(arg-> text .length ())-1 );
335
337
// Allow a switch to start with either - or /
336
- if (arg. text .starts_with (" -" + flag.name .substr (0 , length_to_match)) ||
337
- arg. text .starts_with (" /" + flag.name .substr (0 , length_to_match)) ||
338
- arg. text == " -" + flag.synonym ||
339
- arg. text == " /" + flag.synonym
338
+ if (arg-> text .starts_with (" -" + flag.name .substr (0 , length_to_match)) ||
339
+ arg-> text .starts_with (" /" + flag.name .substr (0 , length_to_match)) ||
340
+ arg-> text == " -" + flag.synonym ||
341
+ arg-> text == " /" + flag.synonym
340
342
)
341
343
{
342
- flag.handler ();
343
- arg.pos = processed;
344
+ assert (flag.handler0 || flag.handler1 );
345
+
346
+ // If this is a standalone switch, just process it
347
+ if (flag.handler0 ) {
348
+ flag.handler0 ();
349
+ }
350
+
351
+ // Else this is a switch that takes the next arg as its value, so pass that
352
+ else {
353
+ if (arg+1 == args.end ()) {
354
+ print (" Missing argument to option " + arg->text + " (try -help)\n " );
355
+ help_requested = true ;
356
+ }
357
+ arg->pos = processed;
358
+ ++arg; // move to next argument, which is the argument to this switch
359
+ flag.handler1 (arg->text );
360
+ }
361
+
362
+ arg->pos = processed;
344
363
break ;
345
364
}
346
365
}
347
366
348
367
// For now comment this out to try leaving unmatched switches alone, so that
349
368
// Unix absolute filenames work... and in case an absolute filename collides
350
369
// with a legit switch name, also added "--" above... let's see how this works
351
- // if (arg. pos != processed && (arg. text.starts_with("-") || arg. text.starts_with("/"))) {
352
- // arg. pos = processed;
353
- // print("Unknown option: " + arg. text + " (try -help)\n");
370
+ // if (arg-> pos != processed && (arg-> text.starts_with("-") || arg-> text.starts_with("/"))) {
371
+ // arg-> pos = processed;
372
+ // print("Unknown option: " + arg-> text + " (try -help)\n");
354
373
// help_requested = true;
355
374
// }
356
375
}
@@ -391,14 +410,14 @@ class cmdline_processor
391
410
}
392
411
}
393
412
394
- auto add_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym) {
395
- flags.emplace_back ( group, name, description, handler , synonym );
413
+ auto add_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 , std::string_view synonym) {
414
+ flags.emplace_back ( group, name, description, handler0, handler1 , synonym );
396
415
if (max_flag_length < std::ssize (name)) {
397
416
max_flag_length = std::ssize (name);
398
417
}
399
418
}
400
419
struct register_flag {
401
- register_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym = {});
420
+ register_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 = nullptr , std::string_view synonym = {});
402
421
};
403
422
404
423
auto set_args (int argc, char * argv[]) -> void {
@@ -431,15 +450,16 @@ class cmdline_processor
431
450
432
451
} cmdline;
433
452
434
- cmdline_processor::register_flag::register_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym) {
435
- cmdline.add_flag ( group, name, description, handler , synonym );
453
+ cmdline_processor::register_flag::register_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 , std::string_view synonym) {
454
+ cmdline.add_flag ( group, name, description, handler0, handler1 , synonym );
436
455
}
437
456
438
457
static cmdline_processor::register_flag cmd_help (
439
458
0 ,
440
459
" help" ,
441
460
" Print help" ,
442
461
[]{ cmdline.print_help (); },
462
+ nullptr ,
443
463
" ?"
444
464
);
445
465
0 commit comments