OLD | NEW |
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 /** | 5 /** |
6 * This library lets you define parsers for parsing raw command-line arguments | 6 * This library lets you define parsers for parsing raw command-line arguments |
7 * into a set of options and values using [GNU][] and [POSIX][] style options. | 7 * into a set of options and values using [GNU][] and [POSIX][] style options. |
8 * | 8 * |
9 * ## Installing ## | 9 * ## Installing ## |
10 * | 10 * |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 * be followed by a single new line. Options with multi-line help text | 248 * be followed by a single new line. Options with multi-line help text |
249 * will be followed by two new lines. This provides spatial diversity between | 249 * will be followed by two new lines. This provides spatial diversity between |
250 * options. | 250 * options. |
251 * | 251 * |
252 * [posix]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.h
tml#tag_12_02 | 252 * [posix]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.h
tml#tag_12_02 |
253 * [gnu]: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Inte
rfaces | 253 * [gnu]: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Inte
rfaces |
254 * [pub]: http://pub.dartlang.org | 254 * [pub]: http://pub.dartlang.org |
255 */ | 255 */ |
256 library args; | 256 library args; |
257 | 257 |
| 258 import 'package:unmodifiable_collection/unmodifiable_collection.dart'; |
| 259 |
258 import 'src/parser.dart'; | 260 import 'src/parser.dart'; |
259 import 'src/usage.dart'; | 261 import 'src/usage.dart'; |
260 import 'src/options.dart'; | 262 import 'src/options.dart'; |
261 export 'src/options.dart'; | 263 export 'src/options.dart'; |
262 | 264 |
263 /** | 265 /** |
264 * A class for taking a list of raw command line arguments and parsing out | 266 * A class for taking a list of raw command line arguments and parsing out |
265 * options and flags from them. | 267 * options and flags from them. |
266 */ | 268 */ |
267 class ArgParser { | 269 class ArgParser { |
| 270 final Map<String, Option> _options; |
| 271 final Map<String, ArgParser> _commands; |
| 272 |
268 /** | 273 /** |
269 * The options that have been defined for this parser. | 274 * The options that have been defined for this parser. |
270 */ | 275 */ |
271 final Map<String, Option> options = <String, Option>{}; | 276 final Map<String, Option> options; |
272 | 277 |
273 /** | 278 /** |
274 * The commands that have been defined for this parser. | 279 * The commands that have been defined for this parser. |
275 */ | 280 */ |
276 final Map<String, ArgParser> commands = <String, ArgParser>{}; | 281 final Map<String, ArgParser> commands; |
277 | 282 |
278 /** Creates a new ArgParser. */ | 283 /** Creates a new ArgParser. */ |
279 ArgParser(); | 284 factory ArgParser() => |
| 285 new ArgParser._(<String, Option>{}, <String, ArgParser>{}); |
| 286 |
| 287 ArgParser._(Map<String, Option> options, Map<String, ArgParser> commands) : |
| 288 this._options = options, |
| 289 this.options = new UnmodifiableMapView(options), |
| 290 this._commands = commands, |
| 291 this.commands = new UnmodifiableMapView(commands); |
280 | 292 |
281 /** | 293 /** |
282 * Defines a command. | 294 * Defines a command. |
283 * | 295 * |
284 * A command is a named argument which may in turn define its own options and | 296 * A command is a named argument which may in turn define its own options and |
285 * subcommands using the given parser. If [parser] is omitted, implicitly | 297 * subcommands using the given parser. If [parser] is omitted, implicitly |
286 * creates a new one. Returns the parser for the command. | 298 * creates a new one. Returns the parser for the command. |
287 */ | 299 */ |
288 ArgParser addCommand(String name, [ArgParser parser]) { | 300 ArgParser addCommand(String name, [ArgParser parser]) { |
289 // Make sure the name isn't in use. | 301 // Make sure the name isn't in use. |
290 if (commands.containsKey(name)) { | 302 if (_commands.containsKey(name)) { |
291 throw new ArgumentError('Duplicate command "$name".'); | 303 throw new ArgumentError('Duplicate command "$name".'); |
292 } | 304 } |
293 | 305 |
294 if (parser == null) parser = new ArgParser(); | 306 if (parser == null) parser = new ArgParser(); |
295 commands[name] = parser; | 307 _commands[name] = parser; |
296 return parser; | 308 return parser; |
297 } | 309 } |
298 | 310 |
299 /** | 311 /** |
300 * Defines a flag. Throws an [ArgumentError] if: | 312 * Defines a flag. Throws an [ArgumentError] if: |
301 * | 313 * |
302 * * There is already an option named [name]. | 314 * * There is already an option named [name]. |
303 * * There is already an option using abbreviation [abbr]. | 315 * * There is already an option using abbreviation [abbr]. |
304 */ | 316 */ |
305 void addFlag(String name, {String abbr, String help, bool defaultsTo: false, | 317 void addFlag(String name, {String abbr, String help, bool defaultsTo: false, |
(...skipping 13 matching lines...) Expand all Loading... |
319 void callback(value), bool allowMultiple: false}) { | 331 void callback(value), bool allowMultiple: false}) { |
320 _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo, | 332 _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo, |
321 callback, isFlag: false, allowMultiple: allowMultiple); | 333 callback, isFlag: false, allowMultiple: allowMultiple); |
322 } | 334 } |
323 | 335 |
324 void _addOption(String name, String abbr, String help, List<String> allowed, | 336 void _addOption(String name, String abbr, String help, List<String> allowed, |
325 Map<String, String> allowedHelp, defaultsTo, | 337 Map<String, String> allowedHelp, defaultsTo, |
326 void callback(value), {bool isFlag, bool negatable: false, | 338 void callback(value), {bool isFlag, bool negatable: false, |
327 bool allowMultiple: false}) { | 339 bool allowMultiple: false}) { |
328 // Make sure the name isn't in use. | 340 // Make sure the name isn't in use. |
329 if (options.containsKey(name)) { | 341 if (_options.containsKey(name)) { |
330 throw new ArgumentError('Duplicate option "$name".'); | 342 throw new ArgumentError('Duplicate option "$name".'); |
331 } | 343 } |
332 | 344 |
333 // Make sure the abbreviation isn't too long or in use. | 345 // Make sure the abbreviation isn't too long or in use. |
334 if (abbr != null) { | 346 if (abbr != null) { |
335 var existing = findByAbbreviation(abbr); | 347 var existing = findByAbbreviation(abbr); |
336 if (existing != null) { | 348 if (existing != null) { |
337 throw new ArgumentError( | 349 throw new ArgumentError( |
338 'Abbreviation "$abbr" is already used by "${existing.name}".'); | 350 'Abbreviation "$abbr" is already used by "${existing.name}".'); |
339 } | 351 } |
340 } | 352 } |
341 | 353 |
342 options[name] = new Option(name, abbr, help, allowed, allowedHelp, | 354 _options[name] = new Option(name, abbr, help, allowed, allowedHelp, |
343 defaultsTo, callback, isFlag: isFlag, negatable: negatable, | 355 defaultsTo, callback, isFlag: isFlag, negatable: negatable, |
344 allowMultiple: allowMultiple); | 356 allowMultiple: allowMultiple); |
345 } | 357 } |
346 | 358 |
347 /** | 359 /** |
348 * Parses [args], a list of command-line arguments, matches them against the | 360 * Parses [args], a list of command-line arguments, matches them against the |
349 * flags and options defined by this parser, and returns the result. | 361 * flags and options defined by this parser, and returns the result. |
350 * | 362 * |
351 * If [allowTrailingOptions] is set, the parser will continue parsing even | 363 * If [allowTrailingOptions] is set, the parser will continue parsing even |
352 * after it finds an argument that is neither an option nor a command. | 364 * after it finds an argument that is neither an option nor a command. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 orElse: () => null); | 400 orElse: () => null); |
389 } | 401 } |
390 } | 402 } |
391 | 403 |
392 /** | 404 /** |
393 * The results of parsing a series of command line arguments using | 405 * The results of parsing a series of command line arguments using |
394 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed | 406 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed |
395 * command line arguments. | 407 * command line arguments. |
396 */ | 408 */ |
397 class ArgResults { | 409 class ArgResults { |
398 final Map _options; | 410 final Map<String, dynamic> _options; |
399 | 411 |
400 /** | 412 /** |
401 * If these are the results for parsing a command's options, this will be | 413 * If these are the results for parsing a command's options, this will be |
402 * the name of the command. For top-level results, this returns `null`. | 414 * the name of the command. For top-level results, this returns `null`. |
403 */ | 415 */ |
404 final String name; | 416 final String name; |
405 | 417 |
406 /** | 418 /** |
407 * The command that was selected, or `null` if none was. This will contain | 419 * The command that was selected, or `null` if none was. This will contain |
408 * the options that were selected for that command. | 420 * the options that were selected for that command. |
409 */ | 421 */ |
410 final ArgResults command; | 422 final ArgResults command; |
411 | 423 |
412 /** | 424 /** |
413 * The remaining command-line arguments that were not parsed as options or | 425 * The remaining command-line arguments that were not parsed as options or |
414 * flags. If `--` was used to separate the options from the remaining | 426 * flags. If `--` was used to separate the options from the remaining |
415 * arguments, it will not be included in this list. | 427 * arguments, it will not be included in this list. |
416 */ | 428 */ |
417 final List<String> rest; | 429 final List<String> rest; |
418 | 430 |
419 /** Creates a new [ArgResults]. */ | 431 /** Creates a new [ArgResults]. */ |
420 ArgResults(this._options, this.name, this.command, this.rest); | 432 ArgResults(this._options, this.name, this.command, List<String> rest) |
| 433 : this.rest = new UnmodifiableListView(rest); |
421 | 434 |
422 /** Gets the parsed command-line option named [name]. */ | 435 /** Gets the parsed command-line option named [name]. */ |
423 operator [](String name) { | 436 operator [](String name) { |
424 if (!_options.containsKey(name)) { | 437 if (!_options.containsKey(name)) { |
425 throw new ArgumentError( | 438 throw new ArgumentError( |
426 'Could not find an option named "$name".'); | 439 'Could not find an option named "$name".'); |
427 } | 440 } |
428 | 441 |
429 return _options[name]; | 442 return _options[name]; |
430 } | 443 } |
431 | 444 |
432 /** Get the names of the options as an [Iterable]. */ | 445 /** Get the names of the options as an [Iterable]. */ |
433 Iterable<String> get options => _options.keys; | 446 Iterable<String> get options => _options.keys; |
434 } | 447 } |
435 | 448 |
OLD | NEW |