Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: pkg/args/lib/args.dart

Issue 271183002: Modernize the docs for args. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /**
6 * Parser support for transforming raw command-line arguments into a set
7 * of options and values.
8 *
9 * This library supports [GNU][] and [POSIX][] style options, and it works
10 * in both server-side and client-side apps.
11 *
12 * For information on installing this library, see the
13 * [args package on pub.dartlang.org](http://pub.dartlang.org/packages/args).
14 * Here's an example of importing this library:
15 *
16 * import 'package:args/args.dart';
17 *
18 * ## Defining options
19 *
20 * To use this library, first create an [ArgParser]:
21 *
22 * var parser = new ArgParser();
23 *
24 * Then define a set of options on that parser using [addOption()] and
25 * [addFlag()]. Here's the minimal way to create an option named "name":
26 *
27 * parser.addOption('name');
28 *
29 * When an option can only be set or unset (as opposed to taking a string
30 * value), use a flag:
31 *
32 * parser.addFlag('name');
33 *
34 * Flag options, by default, accept a 'no-' prefix to negate the option.
35 * You can disable the 'no-' prefix using the `negatable` parameter:
36 *
37 * parser.addFlag('name', negatable: false);
38 *
39 * **Terminology note:**
40 * From here on out, the term _option_ refers to both regular options and
41 * flags. In cases where the distinction matters, this documentation uses
42 * the term _non-flag option._
43 *
44 * Options can have an optional single-character abbreviation, specified
45 * with the `abbr` parameter:
46 *
47 * parser.addOption('mode', abbr: 'm');
48 * parser.addFlag('verbose', abbr: 'v');
49 *
50 * Options can also have a default value, specified with the `defaultsTo`
51 * parameter. The default value is used when arguments don't specify the
52 * option.
53 *
54 * parser.addOption('mode', defaultsTo: 'debug');
55 * parser.addFlag('verbose', defaultsTo: false);
56 *
57 * The default value for non-flag options can be any [String]. For flags,
58 * it must be a [bool].
59 *
60 * To validate a non-flag option, you can use the `allowed` parameter to
61 * provide an allowed set of values. When you do, the parser throws a
62 * [FormatException] if the value for an option is not in the allowed set.
63 * Here's an example of specifying allowed values:
64 *
65 * parser.addOption('mode', allowed: ['debug', 'release']);
66 *
67 * You can use the `callback` parameter to associate a function with an
68 * option. Later, when parsing occurs, the callback function is invoked
69 * with the value of the option:
70 *
71 * parser.addOption('mode', callback: (mode) => print('Got mode $mode));
72 * parser.addFlag('verbose', callback: (verbose) {
73 * if (verbose) print('Verbose');
74 * });
75 *
76 * The callbacks for all options are called whenever a set of arguments
77 * is parsed. If an option isn't provided in the args, its callback is
78 * passed the default value, or `null` if no default value is set.
79 *
80 * ## Parsing arguments
81 *
82 * Once you have an [ArgParser] set up with some options and flags, you
83 * use it by calling [ArgParser.parse()] with a set of arguments:
84 *
85 * var results = parser.parse(['some', 'command', 'line', 'args']);
86 *
87 * These arguments usually come from the arguments to main
88 * (`main(List<String> arguments`), but you can pass in any list of strings.
89 * The parse() method returns an instance of [ArgResults], a map-like
90 * object that contains the values of the parsed options.
91 *
92 * var parser = new ArgParser();
93 * parser.addOption('mode');
94 * parser.addFlag('verbose', defaultsTo: true);
95 * var results = parser.parse(['--mode', 'debug', 'something', 'else']);
96 *
97 * print(results['mode']); // debug
98 * print(results['verbose']); // true
99 *
100 * By default, the parse() method stops as soon as it reaches `--` by itself
101 * or anything that the parser doesn't recognize as an option, flag, or
102 * option value. If arguments still remain, they go into [ArgResults.rest].
103 *
104 * print(results.rest); // ['something', 'else']
105 *
106 * To continue to parse options found after non-option arguments, call
107 * parse() with `allowTrailingOptions: true`.
108 *
109 * ## Specifying options
110 *
111 * To actually pass in options and flags on the command line, use GNU or
112 * POSIX style. Consider this option:
113 *
114 * parser.addOption('name', abbr: 'n');
115 *
116 * You can specify its value on the command line using any of the following:
117 *
118 * --name=somevalue
119 * --name somevalue
120 * -nsomevalue
121 * -n somevalue
122 *
123 * Consider this flag:
124 *
125 * parser.addFlag('name', abbr: 'n');
126 *
127 * You can set it to true using one of the following:
128 *
129 * --name
130 * -n
131 *
132 * You can set it to false using the following:
133 *
134 * --no-name
135 *
136 * Multiple flag abbreviations can be collapsed into a single argument. Say
137 * you define these flags:
138 *
139 * parser.addFlag('verbose', abbr: 'v');
140 * parser.addFlag('french', abbr: 'f');
141 * parser.addFlag('iambic-pentameter', abbr: 'i');
142 *
143 * You can set all three flags at once:
144 *
145 * -vfi
146 *
147 * By default, an option has only a single value, with later option values
148 * overriding earlier ones; for example:
149 *
150 * var parser = new ArgParser();
151 * parser.addOption('mode');
152 * var results = parser.parse(['--mode', 'on', '--mode', 'off']);
153 * print(results['mode']); // prints 'off'
154 *
155 * If you need multiple values, set the `allowMultiple` parameter. In that
156 * case the option can occur multiple times, and the parse() method returns
157 * a list of values:
158 *
159 * var parser = new ArgParser();
160 * parser.addOption('mode', allowMultiple: true);
161 * var results = parser.parse(['--mode', 'on', '--mode', 'off']);
162 * print(results['mode']); // prints '[on, off]'
163 *
164 * ## Defining commands ##
165 *
166 * In addition to *options*, you can also define *commands*. A command is
167 * a named argument that has its own set of options. For example, consider
168 * this shell command:
169 *
170 * $ git commit -a
171 *
172 * The executable is `git`, the command is `commit`, and the `-a` option is
173 * an option passed to the command. You can add a command using the
174 * [addCommand] method:
175 *
176 * var parser = new ArgParser();
177 * var command = parser.addCommand('commit');
178 *
179 * The addCommand() method returns another [ArgParser], which you can then
180 * use to define options specific to that command. If you already have an
181 * [ArgParser] for the command's options, you can pass it to addCommand:
182 *
183 * var parser = new ArgParser();
184 * var command = new ArgParser();
185 * parser.addCommand('commit', command);
186 *
187 * The [ArgParser] for a command can then define options or flags:
188 *
189 * command.addFlag('all', abbr: 'a');
190 *
191 * You can add multiple commands to the same parser so that a user can select
192 * one from a range of possible commands. When parsing an argument list,
193 * you can then determine which command was entered and what options were
194 * provided for it.
195 *
196 * var results = parser.parse(['commit', '-a']);
197 * print(results.command.name); // "commit"
198 * print(results.command['all']); // true
199 *
200 * Options for a command must appear after the command in the argument list.
201 * For example, given the above parser, "git -a commit" is *not* valid. The
202 * parser tries to find the right-most command that accepts an option. For
203 * example:
204 *
205 * var parser = new ArgParser();
206 * parser.addFlag('all', abbr: 'a');
207 * var command = parser.addCommand('commit');
208 * command.addFlag('all', abbr: 'a');
209 *
210 * var results = parser.parse(['commit', '-a']);
211 * print(results.command['all']); // true
212 *
213 * Here, both the top-level parser and the "commit" command can accept a
214 * "-a" (which is probably a bad command line interface, admittedly). In
215 * that case, when "-a" appears after "commit", it is applied to that
216 * command. If it appears to the left of "commit", it is given to the
217 * top-level parser.
218 *
219 * ## Displaying usage
220 *
221 * You can automatically generate nice help text, suitable for use as the
222 * output of `--help`. To display good usage information, you should
223 * provide some help text when you create your options.
224 *
225 * To define help text for an entire option, use the `help` parameter:
226 *
227 * parser.addOption('mode', help: 'The compiler configuration',
228 * allowed: ['debug', 'release']);
229 * parser.addFlag('verbose', help: 'Show additional diagnostic info');
230 *
231 * For non-flag options, you can also provide detailed help for each expected
232 * value by using the `allowedHelp` parameter:
233 *
234 * parser.addOption('arch', help: 'The architecture to compile for',
235 * allowedHelp: {
236 * 'ia32': 'Intel x86',
237 * 'arm': 'ARM Holding 32-bit chip'
238 * });
239 *
240 * To display the help, use the ArgParser getUsage() method:
241 *
242 * print(parser.getUsage());
243 *
244 * The resulting string looks something like this:
245 *
246 * --mode The compiler configuration
247 * [debug, release]
248 *
249 * --[no-]verbose Show additional diagnostic info
250 * --arch The architecture to compile for
251 *
252 * [arm] ARM Holding 32-bit chip
253 * [ia32] Intel x86
254 *
255 * To assist the formatting of the usage help, single-line help text is
256 * followed by a single new line. Options with multi-line help text are
257 * followed by two new lines. This provides spatial diversity between options.
258 *
259 * [posix]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.h tml#tag_12_02
260 * [gnu]: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Inte rfaces
261 */
262 library args; 5 library args;
263 6
264 import 'package:collection/wrappers.dart'; 7 import 'package:collection/wrappers.dart';
265 8
266 import 'src/parser.dart'; 9 import 'src/parser.dart';
267 import 'src/usage.dart'; 10 import 'src/usage.dart';
268 import 'src/options.dart'; 11 import 'src/options.dart';
269 export 'src/options.dart'; 12 export 'src/options.dart';
270 13
271 /** 14 /// A class for taking a list of raw command line arguments and parsing out
272 * A class for taking a list of raw command line arguments and parsing out 15 /// options and flags from them.
273 * options and flags from them.
274 */
275 class ArgParser { 16 class ArgParser {
276 final Map<String, Option> _options; 17 final Map<String, Option> _options;
277 final Map<String, ArgParser> _commands; 18 final Map<String, ArgParser> _commands;
278 19
279 /** 20 /// The options that have been defined for this parser.
280 * The options that have been defined for this parser.
281 */
282 final Map<String, Option> options; 21 final Map<String, Option> options;
283 22
284 /** 23 /// The commands that have been defined for this parser.
285 * The commands that have been defined for this parser.
286 */
287 final Map<String, ArgParser> commands; 24 final Map<String, ArgParser> commands;
288 25
289 /** 26 /// Whether or not this parser parses options that appear after non-option
290 * Whether or not this parser parses options that appear after non-option 27 /// arguments.
291 * arguments.
292 */
293 final bool allowTrailingOptions; 28 final bool allowTrailingOptions;
294 29
295 /** 30 /// Creates a new ArgParser.
296 * Creates a new ArgParser. 31 ///
297 * 32 /// If [allowTrailingOptions] is set, the parser will continue parsing even
298 * If [allowTrailingOptions] is set, the parser will continue parsing even 33 /// after it finds an argument that is neither an option nor a command.
299 * after it finds an argument that is neither an option nor a command. 34 /// This allows options to be specified after regular arguments. Defaults to
300 * This allows options to be specified after regular arguments. Defaults to 35 /// `false`.
301 * `false`.
302 */
303 factory ArgParser({bool allowTrailingOptions}) => 36 factory ArgParser({bool allowTrailingOptions}) =>
304 new ArgParser._(<String, Option>{}, <String, ArgParser>{}, 37 new ArgParser._(<String, Option>{}, <String, ArgParser>{},
305 allowTrailingOptions: allowTrailingOptions); 38 allowTrailingOptions: allowTrailingOptions);
306 39
307 ArgParser._(Map<String, Option> options, Map<String, ArgParser> commands, 40 ArgParser._(Map<String, Option> options, Map<String, ArgParser> commands,
308 {bool allowTrailingOptions}) : 41 {bool allowTrailingOptions}) :
309 this._options = options, 42 this._options = options,
310 this.options = new UnmodifiableMapView(options), 43 this.options = new UnmodifiableMapView(options),
311 this._commands = commands, 44 this._commands = commands,
312 this.commands = new UnmodifiableMapView(commands), 45 this.commands = new UnmodifiableMapView(commands),
313 this.allowTrailingOptions = allowTrailingOptions != null ? 46 this.allowTrailingOptions = allowTrailingOptions != null ?
314 allowTrailingOptions : false; 47 allowTrailingOptions : false;
315 48
316 /** 49 /// Defines a command.
317 * Defines a command. 50 ///
318 * 51 /// A command is a named argument which may in turn define its own options and
319 * A command is a named argument which may in turn define its own options and 52 /// subcommands using the given parser. If [parser] is omitted, implicitly
320 * subcommands using the given parser. If [parser] is omitted, implicitly 53 /// creates a new one. Returns the parser for the command.
321 * creates a new one. Returns the parser for the command.
322 */
323 ArgParser addCommand(String name, [ArgParser parser]) { 54 ArgParser addCommand(String name, [ArgParser parser]) {
324 // Make sure the name isn't in use. 55 // Make sure the name isn't in use.
325 if (_commands.containsKey(name)) { 56 if (_commands.containsKey(name)) {
326 throw new ArgumentError('Duplicate command "$name".'); 57 throw new ArgumentError('Duplicate command "$name".');
327 } 58 }
328 59
329 if (parser == null) parser = new ArgParser(); 60 if (parser == null) parser = new ArgParser();
330 _commands[name] = parser; 61 _commands[name] = parser;
331 return parser; 62 return parser;
332 } 63 }
333 64
334 /** 65 /// Defines a flag. Throws an [ArgumentError] if:
335 * Defines a flag. Throws an [ArgumentError] if: 66 ///
336 * 67 /// * There is already an option named [name].
337 * * There is already an option named [name]. 68 /// * There is already an option using abbreviation [abbr].
338 * * There is already an option using abbreviation [abbr].
339 */
340 void addFlag(String name, {String abbr, String help, bool defaultsTo: false, 69 void addFlag(String name, {String abbr, String help, bool defaultsTo: false,
341 bool negatable: true, void callback(bool value), bool hide: false}) { 70 bool negatable: true, void callback(bool value), bool hide: false}) {
342 _addOption(name, abbr, help, null, null, defaultsTo, callback, 71 _addOption(name, abbr, help, null, null, defaultsTo, callback,
343 isFlag: true, negatable: negatable, hide: hide); 72 isFlag: true, negatable: negatable, hide: hide);
344 } 73 }
345 74
346 /** 75 /// Defines a value-taking option. Throws an [ArgumentError] if:
347 * Defines a value-taking option. Throws an [ArgumentError] if: 76 ///
348 * 77 /// * There is already an option with name [name].
349 * * There is already an option with name [name]. 78 /// * There is already an option using abbreviation [abbr].
350 * * There is already an option using abbreviation [abbr].
351 */
352 void addOption(String name, {String abbr, String help, List<String> allowed, 79 void addOption(String name, {String abbr, String help, List<String> allowed,
353 Map<String, String> allowedHelp, String defaultsTo, 80 Map<String, String> allowedHelp, String defaultsTo,
354 void callback(value), bool allowMultiple: false, bool hide: false}) { 81 void callback(value), bool allowMultiple: false, bool hide: false}) {
355 _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo, 82 _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo,
356 callback, isFlag: false, allowMultiple: allowMultiple, 83 callback, isFlag: false, allowMultiple: allowMultiple,
357 hide: hide); 84 hide: hide);
358 } 85 }
359 86
360 void _addOption(String name, String abbr, String help, List<String> allowed, 87 void _addOption(String name, String abbr, String help, List<String> allowed,
361 Map<String, String> allowedHelp, defaultsTo, 88 Map<String, String> allowedHelp, defaultsTo,
(...skipping 11 matching lines...) Expand all
373 throw new ArgumentError( 100 throw new ArgumentError(
374 'Abbreviation "$abbr" is already used by "${existing.name}".'); 101 'Abbreviation "$abbr" is already used by "${existing.name}".');
375 } 102 }
376 } 103 }
377 104
378 _options[name] = new Option(name, abbr, help, allowed, allowedHelp, 105 _options[name] = new Option(name, abbr, help, allowed, allowedHelp,
379 defaultsTo, callback, isFlag: isFlag, negatable: negatable, 106 defaultsTo, callback, isFlag: isFlag, negatable: negatable,
380 allowMultiple: allowMultiple, hide: hide); 107 allowMultiple: allowMultiple, hide: hide);
381 } 108 }
382 109
383 /** 110 /// Parses [args], a list of command-line arguments, matches them against the
384 * Parses [args], a list of command-line arguments, matches them against the 111 /// flags and options defined by this parser, and returns the result.
385 * flags and options defined by this parser, and returns the result.
386 */
387 ArgResults parse(List<String> args) => 112 ArgResults parse(List<String> args) =>
388 new Parser(null, this, args.toList(), null, null).parse(); 113 new Parser(null, this, args.toList(), null, null).parse();
389 114
390 /** 115 /// Generates a string displaying usage information for the defined options.
391 * Generates a string displaying usage information for the defined options. 116 /// This is basically the help text shown on the command line.
392 * This is basically the help text shown on the command line.
393 */
394 String getUsage() => new Usage(this).generate(); 117 String getUsage() => new Usage(this).generate();
395 118
396 /** 119 /// Get the default value for an option. Useful after parsing to test if the
397 * Get the default value for an option. Useful after parsing to test 120 /// user specified something other than the default.
398 * if the user specified something other than the default.
399 */
400 getDefault(String option) { 121 getDefault(String option) {
401 if (!options.containsKey(option)) { 122 if (!options.containsKey(option)) {
402 throw new ArgumentError('No option named $option'); 123 throw new ArgumentError('No option named $option');
403 } 124 }
404 return options[option].defaultValue; 125 return options[option].defaultValue;
405 } 126 }
406 127
407 /** 128 /// Finds the option whose abbreviation is [abbr], or `null` if no option has
408 * Finds the option whose abbreviation is [abbr], or `null` if no option has 129 /// that abbreviation.
409 * that abbreviation.
410 */
411 Option findByAbbreviation(String abbr) { 130 Option findByAbbreviation(String abbr) {
412 return options.values.firstWhere((option) => option.abbreviation == abbr, 131 return options.values.firstWhere((option) => option.abbreviation == abbr,
413 orElse: () => null); 132 orElse: () => null);
414 } 133 }
415 } 134 }
416 135
417 /** 136 /// The results of parsing a series of command line arguments using
418 * The results of parsing a series of command line arguments using 137 /// [ArgParser.parse()]. Includes the parsed options and any remaining unparsed
419 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed 138 /// command line arguments.
420 * command line arguments.
421 */
422 class ArgResults { 139 class ArgResults {
423 final Map<String, dynamic> _options; 140 final Map<String, dynamic> _options;
424 141
425 /** 142 /// If these are the results for parsing a command's options, this will be the
426 * If these are the results for parsing a command's options, this will be 143 /// name of the command. For top-level results, this returns `null`.
427 * the name of the command. For top-level results, this returns `null`.
428 */
429 final String name; 144 final String name;
430 145
431 /** 146 /// The command that was selected, or `null` if none was. This will contain
432 * The command that was selected, or `null` if none was. This will contain 147 /// the options that were selected for that command.
433 * the options that were selected for that command.
434 */
435 final ArgResults command; 148 final ArgResults command;
436 149
437 /** 150 /// The remaining command-line arguments that were not parsed as options or
438 * The remaining command-line arguments that were not parsed as options or 151 /// flags. If `--` was used to separate the options from the remaining
439 * flags. If `--` was used to separate the options from the remaining 152 /// arguments, it will not be included in this list.
440 * arguments, it will not be included in this list.
441 */
442 final List<String> rest; 153 final List<String> rest;
443 154
444 /** Creates a new [ArgResults]. */ 155 /// Creates a new [ArgResults].
445 ArgResults(this._options, this.name, this.command, List<String> rest) 156 ArgResults(this._options, this.name, this.command, List<String> rest)
446 : this.rest = new UnmodifiableListView(rest); 157 : this.rest = new UnmodifiableListView(rest);
447 158
448 /** Gets the parsed command-line option named [name]. */ 159 /// Gets the parsed command-line option named [name].
449 operator [](String name) { 160 operator [](String name) {
450 if (!_options.containsKey(name)) { 161 if (!_options.containsKey(name)) {
451 throw new ArgumentError( 162 throw new ArgumentError(
452 'Could not find an option named "$name".'); 163 'Could not find an option named "$name".');
453 } 164 }
454 165
455 return _options[name]; 166 return _options[name];
456 } 167 }
457 168
458 /** Get the names of the options as an [Iterable]. */ 169 /// Get the names of the options as an [Iterable].
459 Iterable<String> get options => _options.keys; 170 Iterable<String> get options => _options.keys;
460 } 171 }
461 172
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698