Changeset 84
- Timestamp:
- 01/14/07 06:20:39 (2 years ago)
- Files:
-
- misc/tango/optparse.d (modified) (27 diffs)
- misc/tango/opttest.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
misc/tango/optparse.d
r83 r84 22 22 /** 23 23 * Command-line option parsing, in the style of Python's optparse. 24 * 25 * Refer to the complete docs for more information. 24 26 */ 25 27 module optparse; … … 83 85 } 84 86 85 // Thrown if client code tries to set up an improper option.87 /// Thrown if client code tries to set up an improper option. 86 88 class OptionError : Exception { 87 89 this(char[] msg) { super(msg); } … … 92 94 } 93 95 96 /++ 97 This class represents the results after parsing the command-line. 98 +/ 94 99 class Options { 95 100 char[][][char[]] opts; 96 101 int[char[]] counted_opts; 102 /// By default, leftover arguments are placed in this array. 97 103 char[][] args; 98 104 105 /// Retrieves the results of the Store and StoreConst actions. 99 106 char[] opIndex(char[] opt) { 100 107 char[][]* o = opt in opts; … … 105 112 } 106 113 } 114 /// Retrieves the results of the Store action, when the type is Integer. 107 115 int value(char[] opt) { 108 116 char[][]* o = opt in opts; … … 113 121 } 114 122 } 123 /// Retrieves the results of the Append and AppendConst actions. 115 124 char[][] list(char[] opt) { 116 125 char[][]* o = opt in opts; … … 121 130 } 122 131 } 123 int[] value_list(char[] opt) { 132 /// Retrieves the results of the Append action, when the type is Integer. 133 int[] valueList(char[] opt) { 124 134 char[][]* o = opt in opts; 125 135 int[] l; … … 132 142 return l; 133 143 } 144 /// Retrieves the results of the Count action. 134 145 int count(char[] opt) { 135 146 int* c = opt in counted_opts; … … 140 151 } 141 152 } 153 /// Retrieves the results of the SetTrue and SetFalse actions. 142 154 bool flag(char[] opt) { 143 155 char[][]* o = opt in opts; … … 151 163 152 164 // Options, args, this opt's index in args, name[, arg] 165 /// 153 166 alias void delegate(Options, inout char[][], inout int, char[], char[]) OptionCallbackFancyArg; 167 /// 154 168 alias void delegate(Options, inout char[][], inout int, char[], int) OptionCallbackFancyInt; 169 /// 155 170 alias void delegate(Options, inout char[][], inout int, char[]) OptionCallbackFancy; 156 171 172 /// 157 173 alias void delegate(char[]) OptionCallbackArg; 174 /// 158 175 alias void delegate(int) OptionCallbackInt; 176 /// 159 177 alias void delegate() OptionCallback; 160 178 … … 169 187 * CallbackVoid: dg 170 188 */ 171 enum Action { Store, StoreConst, Append, AppendConst, Count, SetTrue, SetFalse, Callback, CallbackFancy, Help } 172 enum ArgType { None, String, Integer } 189 /// 190 enum Action { /+++/Store, /+++/StoreConst, /+++/Append, /+++/AppendConst, /+++/Count, /+++/SetTrue, /+++/SetFalse, /+++/Callback, /+++/CallbackFancy, /+++/Help /+++/} 191 /// 192 enum ArgType { /+++/None, /+++/String, /+++/Integer /+++/} 173 193 174 194 ArgType defaultType(Action action) { … … 183 203 } 184 204 205 /++ 206 This class represents a single command-line option. 207 +/ 185 208 class Option { 186 209 char[][] shortopts, longopts; … … 275 298 } 276 299 // Does whatever this option is supposed to do. 277 void perform _action(OptionParser parser, Options results, inout char[][] args, inout int idx, char[] arg) {300 void performAction(OptionParser parser, Options results, inout char[][] args, inout int idx, char[] arg) { 278 301 int i; 279 302 if (this.type == ArgType.Integer) { … … 333 356 break; 334 357 case Action.Help: 335 parser.help _text();358 parser.helpText(); 336 359 exit(EXIT_SUCCESS); 337 360 break; 338 361 } 339 362 } 363 /// Returns whether this option accepts an argument. 340 364 bool hasArg() { 341 365 return this.type != ArgType.None; 342 366 } 367 /// Sets the help text for this option. 343 368 Option help(char[] help) { 344 369 this.helptext = help; 345 370 return this; 346 371 } 372 /// Sets the name of this option's argument, if it has one. 347 373 Option argName(char[] argname) { 348 374 this.argname = argname; … … 376 402 } 377 403 404 /++ 405 This class is used to define a set of options, and parse the command-line 406 arguments. 407 +/ 378 408 class OptionParser { 379 409 OptionCallbackArg leftover_cb; 410 /// An array of all of the options known by this parser. 380 411 Option[] options; 381 char[] name, desc, argdesc; 412 char[] name, desc; 413 /// The description of the programs arguments, as used in the Help action. 414 char[] argdesc; 382 415 private void delegate(char[]) error_callback; 383 416 … … 388 421 } 389 422 390 void set_error_callback(void delegate(char[]) dg) { 423 /// Sets a callback, to override the default error behavior. 424 void setErrorCallback(void delegate(char[]) dg) { 391 425 error_callback = dg; 392 426 } 393 void unknown _opt_error(char[] opt) {427 void unknownOptError(char[] opt) { 394 428 error("Unknown argument '"~opt~"'"); 395 429 } 396 void expected _arg_error(char[] opt) {430 void expectedArgError(char[] opt) { 397 431 error("'"~opt~"' option expects an argument."); 398 432 } 433 /// Displays an error message and terminates the program. 399 434 void error(char[] err) { 400 435 if (error_callback !is null) { 401 436 error_callback(err); 402 437 } else { 403 this.help _text();438 this.helpText(); 404 439 Stdout.println(err); 405 440 } … … 409 444 int i; 410 445 uint ate; 411 i = parse(s, 10u, &ate);446 i = .parse(s, 10u, &ate); 412 447 if (ate != s.length) 413 448 error("Could not convert '"~s~"' to an integer."); … … 415 450 } 416 451 417 void help_text() { 452 /// Displays useful "help" information about the program's options. 453 void helpText() { 418 454 int optWidth; 419 455 char[][] optStrs; … … 456 492 return path[idx+1 .. $]; 457 493 } 458 char[] get _program_name(char[] path) {494 char[] getProgramName(char[] path) { 459 495 version(Windows) { 460 496 // (Unicode note: ".exe" only contains 4 code units, so this slice … … 467 503 return getBaseName(path); 468 504 } 469 Options parse_args(char[][] args) { 470 this.name = get_program_name(args[0]); 505 /// Parses the passed command-line arguments and returns the results. 506 Options parse(char[][] args) { 507 this.name = getProgramName(args[0]); 471 508 args = args[1 .. $]; 472 509 Options options = new Options; … … 521 558 match = matches(newopt); 522 559 if (match is null) { 523 unknown _opt_error(newopt);560 unknownOptError(newopt); 524 561 } 525 562 if (match.hasArg) { 526 if (i == args.length-1) expected _arg_error(match.name);563 if (i == args.length-1) expectedArgError(match.name); 527 564 arg = args[i+1]; 528 565 ++i; … … 530 567 arg = null; 531 568 } 532 match.perform _action(this, options, args, i, arg);569 match.performAction(this, options, args, i, arg); 533 570 } else if (opt.startswith("-")) { 534 571 if (opt.length >= 2) { … … 538 575 match = matches(newopt); 539 576 if (match is null) { 540 unknown _opt_error(newopt);577 unknownOptError(newopt); 541 578 } 542 579 if (match.hasArg) { … … 544 581 // next element of args for the arg. 545 582 if (j == opt32.length-1) { 546 if (i == args.length-1) expected _arg_error(match.name);583 if (i == args.length-1) expectedArgError(match.name); 547 584 arg = args[i+1]; 548 585 ++i; … … 551 588 } else { 552 589 arg = .toUtf8(opt32[j+1 .. $]); 553 match.perform _action(this, options, args, i, arg);590 match.performAction(this, options, args, i, arg); 554 591 break; 555 592 } … … 557 594 arg = null; 558 595 } 559 match.perform _action(this, options, args, i, arg);596 match.performAction(this, options, args, i, arg); 560 597 } 561 598 } else { 562 unknown _opt_error(opt);599 unknownOptError(opt); 563 600 } 564 601 } else { … … 573 610 } 574 611 575 void leftover_callback(OptionCallbackArg dg) { 612 /++ 613 Overrides the default behavior of leftover arguments, calling this callback 614 with them instead of adding them an array. 615 +/ 616 void leftoverCallback(OptionCallbackArg dg) { 576 617 this.leftover_cb = dg; 577 618 } 578 Option add_option(Option option) { 619 /// 620 Option addOption(Option option) { 579 621 this.options ~= option; 580 622 return option; 581 623 } 582 624 // options action name type const_value dga dgv dgi fdga fdgi fdg 583 Option add_option(char[][] options ...) { 584 return add_option(options, Action.Store, null, defaultType(Action.Store), null, null, null, null, null, null, null); 585 } 586 Option add_option(char[][] options, char[] name) { 587 return add_option(options, Action.Store, name, defaultType(Action.Store), null, null, null, null, null, null, null); 588 } 589 Option add_option(char[][] options, Action action) { 590 return add_option(options, action, null, defaultType(action), null, null, null, null, null, null, null); 591 } 592 Option add_option(char[][] options, ArgType type) { 593 return add_option(options, Action.Store, null, type, null, null, null, null, null, null, null); 594 } 595 Option add_option(char[][] options, Action action, ArgType type) { 596 return add_option(options, action, null, type, null, null, null, null, null, null, null); 597 } 598 Option add_option(char[][] options, char[] name, Action action) { 599 return add_option(options, action, name, defaultType(action), null, null, null, null, null, null, null); 600 } 601 Option add_option(char[][] options, char[] name, Action action, ArgType type) { 602 return add_option(options, action, name, type, null, null, null, null, null, null, null); 603 } 604 Option add_option(char[][] options, Action action, char[] const_value) { 605 return add_option(options, action, null, defaultType(action), const_value, null, null, null, null, null, null); 606 } 607 Option add_option(char[][] options, char[] name, char[] const_value) { 608 return add_option(options, Action.StoreConst, name, defaultType(Action.Store), const_value, null, null, null, null, null, null); 609 } 610 Option add_option(char[][] options, char[] name, Action action, char[] const_value) { 611 return add_option(options, action, name, defaultType(action), const_value, null, null, null, null, null, null); 612 } 613 Option add_option(char[][] options, OptionCallbackArg dg) { 614 return add_option(options, Action.Callback, null, ArgType.String, null, dg, null, null, null, null, null); 615 } 616 Option add_option(char[][] options, OptionCallback dg) { 617 return add_option(options, Action.Callback, null, ArgType.None, null, null, dg, null, null, null, null); 618 } 619 Option add_option(char[][] options, OptionCallbackInt dg) { 620 return add_option(options, Action.Callback, null, ArgType.Integer, null, null, null, dg, null, null, null); 621 } 622 Option add_option(char[][] options, OptionCallbackFancyArg dg) { 623 return add_option(options, Action.CallbackFancy, null, ArgType.String, null, null, null, null, dg, null, null); 624 } 625 Option add_option(char[][] options, OptionCallbackFancy dg) { 626 return add_option(options, Action.CallbackFancy, null, ArgType.None, null, null, null, null, null, null, dg); 627 } 628 Option add_option(char[][] options, OptionCallbackFancyInt dg) { 629 return add_option(options, Action.CallbackFancy, null, ArgType.Integer, null, null, null, null, null, dg, null); 630 } 631 Option add_option(char[][] options, char[] name, OptionCallbackFancyArg dg) { 632 return add_option(options, Action.CallbackFancy, name, ArgType.String, null, null, null, null, dg, null, null); 633 } 634 Option add_option(char[][] options, char[] name, OptionCallbackFancy dg) { 635 return add_option(options, Action.CallbackFancy, name, ArgType.None, null, null, null, null, null, null, dg); 636 } 637 Option add_option(char[][] options, char[] name, OptionCallbackFancyInt dg) { 638 return add_option(options, Action.CallbackFancy, name, ArgType.Integer, null, null, null, null, null, dg, null); 625 /// 626 Option addOption(char[][] options ...) { 627 return addOption(options, Action.Store, null, defaultType(Action.Store), null, null, null, null, null, null, null); 628 } 629 /// 630 Option addOption(char[][] options, char[] name) { 631 return addOption(options, Action.Store, name, defaultType(Action.Store), null, null, null, null, null, null, null); 632 } 633 /// 634 Option addOption(char[][] options, Action action) { 635 return addOption(options, action, null, defaultType(action), null, null, null, null, null, null, null); 636 } 637 /// 638 Option addOption(char[][] options, ArgType type) { 639 return addOption(options, Action.Store, null, type, null, null, null, null, null, null, null); 640 } 641 /// 642 Option addOption(char[][] options, Action action, ArgType type) { 643 return addOption(options, action, null, type, null, null, null, null, null, null, null); 644 } 645 /// 646 Option addOption(char[][] options, char[] name, Action action) { 647 return addOption(options, action, name, defaultType(action), null, null, null, null, null, null, null); 648 } 649 /// 650 Option addOption(char[][] options, char[] name, Action action, ArgType type) { 651 return addOption(options, action, name, type, null, null, null, null, null, null, null); 652 } 653 /// 654 Option addOption(char[][] options, Action action, char[] const_value) { 655 return addOption(options, action, null, defaultType(action), const_value, null, null, null, null, null, null); 656 } 657 /// 658 Option addOption(char[][] options, char[] name, char[] const_value) { 659 return addOption(options, Action.StoreConst, name, defaultType(Action.Store), const_value, null, null, null, null, null, null); 660 } 661 /// 662 Option addOption(char[][] options, char[] name, Action action, char[] const_value) { 663 return addOption(options, action, name, defaultType(action), const_value, null, null, null, null, null, null); 664 } 665 /// 666 Option addOption(char[][] options, OptionCallbackArg dg) { 667 return addOption(options, Action.Callback, null, ArgType.String, null, dg, null, null, null, null, null); 668 } 669 /// 670 Option addOption(char[][] options, OptionCallback dg) { 671 return addOption(options, Action.Callback, null, ArgType.None, null, null, dg, null, null, null, null); 672 } 673 /// 674 Option addOption(char[][] options, OptionCallbackInt dg) { 675 return addOption(options, Action.Callback, null, ArgType.Integer, null, null, null, dg, null, null, null); 676 } 677 /// 678 Option addOption(char[][] options, OptionCallbackFancyArg dg) { 679 return addOption(options, Action.CallbackFancy, null, ArgType.String, null, null, null, null, dg, null, null); 680 } 681 /// 682 Option addOption(char[][] options, OptionCallbackFancy dg) { 683 return addOption(options, Action.CallbackFancy, null, ArgType.None, null, null, null, null, null, null, dg); 684 } 685 /// 686 Option addOption(char[][] options, OptionCallbackFancyInt dg) { 687 return addOption(options, Action.CallbackFancy, null, ArgType.Integer, null, null, null, null, null, dg, null); 688 } 689 /// 690 Option addOption(char[][] options, char[] name, OptionCallbackFancyArg dg) { 691 return addOption(options, Action.CallbackFancy, name, ArgType.String, null, null, null, null, dg, null, null); 692 } 693 /// 694 Option addOption(char[][] options, char[] name, OptionCallbackFancy dg) { 695 return addOption(options, Action.CallbackFancy, name, ArgType.None, null, null, null, null, null, null, dg); 696 } 697 /// 698 Option addOption(char[][] options, char[] name, OptionCallbackFancyInt dg) { 699 return addOption(options, Action.CallbackFancy, name, ArgType.Integer, null, null, null, null, null, dg, null); 639 700 } 640 701 // Although users certainly /can/ call this, all those overloads are there 641 702 // for a reason. 642 Option add _option(703 Option addOption( 643 704 char[][] options, 644 705 Action action, char[] name, ArgType type, char[] const_value, … … 684 745 else 685 746 throw new OptionError( 686 "No options provided to add _option!"747 "No options provided to addOption!" 687 748 ); 688 749 } misc/tango/opttest.d
r83 r84 22 22 Stdout.formatln("verbosity: {0}", options.count("verbose")); 23 23 Stdout.formatln("value: {0}", options.value("value")); 24 Stdout.formatln("number list: {0}", format_arr(options.value _list("list")));24 Stdout.formatln("number list: {0}", format_arr(options.valueList("list"))); 25 25 Stdout.formatln("switch: {0}", options.flag("switch")); 26 26 Stdout.formatln("args: {0}", format_arr(options.args)); … … 29 29 int main(char[][] args) { 30 30 format = new Format!(char); 31 Stdout.println(format_arr(args));31 //Stdout.println(format_arr(args)); 32 32 auto parser = new OptionParser("A test suite for optparser."); 33 parser.add _option("-f", "--file").help("Stores a single argument.");34 parser.add _option(["-I", "--import"], "importPath", Action.Append).help("Adds arguments to a list.");35 parser.add _option(["-c", "--callback"], {33 parser.addOption("-f", "--file").help("Stores a single argument."); 34 parser.addOption(["-I", "--import"], "importPath", Action.Append).help("Adds arguments to a list."); 35 parser.addOption(["-c", "--callback"], { 36 36 Stdout.formatln("callback encountered"); 37 37 }).help("Calls a callback."); 38 parser.add _option(["-n", "--number"], (int i) {38 parser.addOption(["-n", "--number"], (int i) { 39 39 Stdout.formatln("number callback: {0} * 2 = {1}", i, i*2); 40 40 }).help("Calls a callback with a number."); 41 41 // A fancy callback 42 parser.add _option(["--fancy"], "a callback", (Options opts, inout char[][] a, inout int i, char[] name) {42 parser.addOption(["--fancy"], "a callback", (Options opts, inout char[][] a, inout int i, char[] name) { 43 43 Stdout.formatln("Current file: {0}", opts["file"]); 44 44 Stdout.formatln("Remaining args: {0}", a[i+1 .. $]); … … 47 47 Stdout.formatln("This arg's name: {0}", name); 48 48 }).help("Tests optparse's fancy callbacks."); 49 parser.add _option(["--enable"], "switch", Action.SetTrue).help("Enables the switch.");50 parser.add _option(["--disable"], "switch", Action.SetFalse).help("Disables the switch.");51 parser.add _option(["-V", "--value"], ArgType.Integer).help("Stores a single number").argName("NUMBER");52 parser.add _option(["-l", "--list"], Action.Append, ArgType.Integer).help("Adds numbers to a list.").argName("NUMBER");53 parser.add _option(["-v", "--verbose"], Action.Count).help("Counts the number of times this option appears.");54 parser.add _option(["-h", "--help"], Action.Help).help("Displays a help message.");55 auto options = parser.parse _args(args);49 parser.addOption(["--enable"], "switch", Action.SetTrue).help("Enables the switch."); 50 parser.addOption(["--disable"], "switch", Action.SetFalse).help("Disables the switch."); 51 parser.addOption(["-V", "--value"], ArgType.Integer).help("Stores a single number").argName("NUMBER"); 52 parser.addOption(["-l", "--list"], Action.Append, ArgType.Integer).help("Adds numbers to a list.").argName("NUMBER"); 53 parser.addOption(["-v", "--verbose"], Action.Count).help("Counts the number of times this option appears."); 54 parser.addOption(["-h", "--help"], Action.Help).help("Displays a help message."); 55 auto options = parser.parse(args); 56 56 57 57 print_opts(options);
