| 1 |
/* |
|---|
| 2 |
Copyright (c) 2007 Kirk McDonald |
|---|
| 3 |
|
|---|
| 4 |
Permission is hereby granted, free of charge, to any person obtaining a copy of |
|---|
| 5 |
this software and associated documentation files (the "Software"), to deal in |
|---|
| 6 |
the Software without restriction, including without limitation the rights to |
|---|
| 7 |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|---|
| 8 |
of the Software, and to permit persons to whom the Software is furnished to do |
|---|
| 9 |
so, subject to the following conditions: |
|---|
| 10 |
|
|---|
| 11 |
The above copyright notice and this permission notice shall be included in all |
|---|
| 12 |
copies or substantial portions of the Software. |
|---|
| 13 |
|
|---|
| 14 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|---|
| 15 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|---|
| 16 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|---|
| 17 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|---|
| 18 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|---|
| 19 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|---|
| 20 |
SOFTWARE. |
|---|
| 21 |
*/ |
|---|
| 22 |
/** |
|---|
| 23 |
* Command-line option parsing, in the style of Python's optparse. |
|---|
| 24 |
* |
|---|
| 25 |
* This is the command-line interface to optparse. |
|---|
| 26 |
*/ |
|---|
| 27 |
module optparse; |
|---|
| 28 |
|
|---|
| 29 |
import optimpl; |
|---|
| 30 |
public import optimpl : Options, Option, Action, ArgType, |
|---|
| 31 |
OptionCallbackFancy, |
|---|
| 32 |
OptionCallbackFancyArg, |
|---|
| 33 |
OptionCallbackFancyInt, |
|---|
| 34 |
OptionCallback, |
|---|
| 35 |
OptionCallbackArg, |
|---|
| 36 |
OptionCallbackInt; |
|---|
| 37 |
|
|---|
| 38 |
version (Tango) { |
|---|
| 39 |
import tango.io.Stdout : Stdout; |
|---|
| 40 |
import tango.stdc.stdlib : exit, EXIT_FAILURE, EXIT_SUCCESS; |
|---|
| 41 |
/+ |
|---|
| 42 |
import tango.text.Util : find = locate, locatePrior; |
|---|
| 43 |
import tango.text.Ascii : toupper = toUpper; |
|---|
| 44 |
import tango.text.convert.Integer : parse, toInt, toString = toUtf8; |
|---|
| 45 |
import tango.text.convert.Utf : toUTF8 = toUtf8, toUTF32 = toUtf32; |
|---|
| 46 |
int getNotFound(char[] s) { |
|---|
| 47 |
return s.length; |
|---|
| 48 |
} |
|---|
| 49 |
//alias char[] string; |
|---|
| 50 |
+/ |
|---|
| 51 |
} else { |
|---|
| 52 |
import std.stdio : writefln, writef; |
|---|
| 53 |
import std.c.stdlib : exit, EXIT_FAILURE, EXIT_SUCCESS; |
|---|
| 54 |
/+ |
|---|
| 55 |
import std.string : find, toupper, toString; |
|---|
| 56 |
import std.conv : toInt, ConvError; |
|---|
| 57 |
import std.path : getBaseName; |
|---|
| 58 |
import std.utf : toUTF8, toUTF32; |
|---|
| 59 |
int getNotFound(char[] s) { |
|---|
| 60 |
return -1; |
|---|
| 61 |
} |
|---|
| 62 |
+/ |
|---|
| 63 |
} |
|---|
| 64 |
|
|---|
| 65 |
/++ |
|---|
| 66 |
This class is used to define a set of options, and parse the command-line |
|---|
| 67 |
arguments. |
|---|
| 68 |
+/ |
|---|
| 69 |
class OptionParser : optimpl.OptionParser { |
|---|
| 70 |
this(char[] desc="") { |
|---|
| 71 |
super(desc); |
|---|
| 72 |
} |
|---|
| 73 |
/// Displays an error message and terminates the program. |
|---|
| 74 |
void error(char[] err) { |
|---|
| 75 |
try { |
|---|
| 76 |
super.error(err); |
|---|
| 77 |
} catch(OptionParsingError e) { |
|---|
| 78 |
version (Tango) { |
|---|
| 79 |
Stdout.formatln("{0}", e); |
|---|
| 80 |
} else { |
|---|
| 81 |
writefln(e); |
|---|
| 82 |
} |
|---|
| 83 |
exit(EXIT_FAILURE); |
|---|
| 84 |
} |
|---|
| 85 |
} |
|---|
| 86 |
/+ |
|---|
| 87 |
Returns an array of arrays of strings with useful "help" information about the program's |
|---|
| 88 |
options. |
|---|
| 89 |
|
|---|
| 90 |
The array looks something like this: |
|---|
| 91 |
[ |
|---|
| 92 |
['option', 'help text'], |
|---|
| 93 |
['option', 'help text'], |
|---|
| 94 |
... |
|---|
| 95 |
] |
|---|
| 96 |
+/ |
|---|
| 97 |
char[][][] helpText() { |
|---|
| 98 |
int optWidth = 0; |
|---|
| 99 |
char[][][] help = super.helpText(); |
|---|
| 100 |
// Calculate the maximum width of the option lists. |
|---|
| 101 |
foreach(i, opt; help) { |
|---|
| 102 |
if (opt[0].length > optWidth) { |
|---|
| 103 |
optWidth = opt[0].length; |
|---|
| 104 |
} |
|---|
| 105 |
} |
|---|
| 106 |
version (Tango) { |
|---|
| 107 |
typedef char spacechar = ' '; |
|---|
| 108 |
spacechar[] padding; |
|---|
| 109 |
Stdout.formatln("Usage: {0} {1}", this.name, this.argdesc); |
|---|
| 110 |
if (this.desc !is null && this.desc != "") Stdout(this.desc).newline; |
|---|
| 111 |
Stdout("\nOptions:").newline; |
|---|
| 112 |
foreach(i, opt; help) { |
|---|
| 113 |
padding.length = optWidth - opt[0].length; |
|---|
| 114 |
Stdout.formatln(" {0}{1} {2}", opt[0], cast(char[])padding, opt[1]); |
|---|
| 115 |
} |
|---|
| 116 |
} else { |
|---|
| 117 |
writefln("Usage: %s %s", this.name, this.argdesc); |
|---|
| 118 |
if (this.desc !is null && this.desc != "") writefln(this.desc); |
|---|
| 119 |
writefln("\nOptions:"); |
|---|
| 120 |
foreach(i, opt; help) { |
|---|
| 121 |
// The commented-out code is a great idea I'll do properly later. |
|---|
| 122 |
//if (opt.helptext.length + optWidth + 3 > 80) { |
|---|
| 123 |
// writefln(" %s\n\t%s", optStrs[i], opt.helptext); |
|---|
| 124 |
//} else { |
|---|
| 125 |
writefln(" %-*s %s", optWidth, opt[0], opt[1]); |
|---|
| 126 |
//} |
|---|
| 127 |
} |
|---|
| 128 |
} |
|---|
| 129 |
return help; |
|---|
| 130 |
} |
|---|
| 131 |
} |
|---|