| 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 library args.src.parser; | 5 library args.src.parser; |
| 6 | 6 |
| 7 import '../args.dart'; | 7 import 'arg_parser.dart'; |
| 8 import 'arg_results.dart'; |
| 9 import 'option.dart'; |
| 8 | 10 |
| 9 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); | 11 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); |
| 10 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); | 12 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); |
| 11 final _LONG_OPT = new RegExp(r'^--([a-zA-Z\-_0-9]+)(=(.*))?$'); | 13 final _LONG_OPT = new RegExp(r'^--([a-zA-Z\-_0-9]+)(=(.*))?$'); |
| 12 | 14 |
| 13 /// The actual argument parsing class. | 15 /// The actual argument parsing class. |
| 14 /// | 16 /// |
| 15 /// Unlike [ArgParser] which is really more an "arg grammar", this is the class | 17 /// Unlike [ArgParser] which is really more an "arg grammar", this is the class |
| 16 /// that does the parsing and holds the mutable state required during a parse. | 18 /// that does the parsing and holds the mutable state required during a parse. |
| 17 class Parser { | 19 class Parser { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 39 if (rest != null) this.rest.addAll(rest); | 41 if (rest != null) this.rest.addAll(rest); |
| 40 } | 42 } |
| 41 | 43 |
| 42 /// The current argument being parsed. | 44 /// The current argument being parsed. |
| 43 String get current => args[0]; | 45 String get current => args[0]; |
| 44 | 46 |
| 45 /// Parses the arguments. This can only be called once. | 47 /// Parses the arguments. This can only be called once. |
| 46 ArgResults parse() { | 48 ArgResults parse() { |
| 47 var commandResults = null; | 49 var commandResults = null; |
| 48 | 50 |
| 49 // Initialize flags to their defaults. | |
| 50 grammar.options.forEach((name, option) { | |
| 51 if (option.allowMultiple) { | |
| 52 results[name] = []; | |
| 53 } else { | |
| 54 results[name] = option.defaultValue; | |
| 55 } | |
| 56 }); | |
| 57 | |
| 58 // Parse the args. | 51 // Parse the args. |
| 59 while (args.length > 0) { | 52 while (args.length > 0) { |
| 60 if (current == '--') { | 53 if (current == '--') { |
| 61 // Reached the argument terminator, so stop here. | 54 // Reached the argument terminator, so stop here. |
| 62 args.removeAt(0); | 55 args.removeAt(0); |
| 63 break; | 56 break; |
| 64 } | 57 } |
| 65 | 58 |
| 66 // Try to parse the current argument as a command. This happens before | 59 // Try to parse the current argument as a command. This happens before |
| 67 // options so that commands can have option-like names. | 60 // options so that commands can have option-like names. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 82 if (parseSoloOption()) continue; | 75 if (parseSoloOption()) continue; |
| 83 if (parseAbbreviation(this)) continue; | 76 if (parseAbbreviation(this)) continue; |
| 84 if (parseLongOption()) continue; | 77 if (parseLongOption()) continue; |
| 85 | 78 |
| 86 // This argument is neither option nor command, so stop parsing unless | 79 // This argument is neither option nor command, so stop parsing unless |
| 87 // the [allowTrailingOptions] option is set. | 80 // the [allowTrailingOptions] option is set. |
| 88 if (!grammar.allowTrailingOptions) break; | 81 if (!grammar.allowTrailingOptions) break; |
| 89 rest.add(args.removeAt(0)); | 82 rest.add(args.removeAt(0)); |
| 90 } | 83 } |
| 91 | 84 |
| 92 // Set unspecified multivalued arguments to their default value, | 85 // Invoke the callbacks. |
| 93 // if any, and invoke the callbacks. | |
| 94 grammar.options.forEach((name, option) { | 86 grammar.options.forEach((name, option) { |
| 95 if (option.allowMultiple && | 87 if (option.callback == null) return; |
| 96 results[name].length == 0 && | 88 option.callback(option.getOrDefault(results[name])); |
| 97 option.defaultValue != null) { | |
| 98 results[name].add(option.defaultValue); | |
| 99 } | |
| 100 if (option.callback != null) option.callback(results[name]); | |
| 101 }); | 89 }); |
| 102 | 90 |
| 103 // Add in the leftover arguments we didn't parse to the innermost command. | 91 // Add in the leftover arguments we didn't parse to the innermost command. |
| 104 rest.addAll(args); | 92 rest.addAll(args); |
| 105 args.clear(); | 93 args.clear(); |
| 106 return new ArgResults(results, commandName, commandResults, rest); | 94 return newArgResults(grammar, results, commandName, commandResults, rest); |
| 107 } | 95 } |
| 108 | 96 |
| 109 /// Pulls the value for [option] from the second argument in [args]. | 97 /// Pulls the value for [option] from the second argument in [args]. |
| 110 /// | 98 /// |
| 111 /// Validates that there is a valid value there. | 99 /// Validates that there is a valid value there. |
| 112 void readNextArgAsValue(Option option) { | 100 void readNextArgAsValue(Option option) { |
| 113 // Take the option argument from the next command line arg. | 101 // Take the option argument from the next command line arg. |
| 114 validate(args.length > 0, | 102 validate(args.length > 0, |
| 115 'Missing argument for "${option.name}".'); | 103 'Missing argument for "${option.name}".'); |
| 116 | 104 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 252 } |
| 265 | 253 |
| 266 /// Validates and stores [value] as the value for [option]. | 254 /// Validates and stores [value] as the value for [option]. |
| 267 void setOption(Map results, Option option, value) { | 255 void setOption(Map results, Option option, value) { |
| 268 // See if it's one of the allowed values. | 256 // See if it's one of the allowed values. |
| 269 if (option.allowed != null) { | 257 if (option.allowed != null) { |
| 270 validate(option.allowed.any((allow) => allow == value), | 258 validate(option.allowed.any((allow) => allow == value), |
| 271 '"$value" is not an allowed value for option "${option.name}".'); | 259 '"$value" is not an allowed value for option "${option.name}".'); |
| 272 } | 260 } |
| 273 | 261 |
| 274 if (option.allowMultiple) { | 262 if (option.isMultiple) { |
| 275 results[option.name].add(value); | 263 var list = results.putIfAbsent(option.name, () => []); |
| 264 list.add(value); |
| 276 } else { | 265 } else { |
| 277 results[option.name] = value; | 266 results[option.name] = value; |
| 278 } | 267 } |
| 279 } | 268 } |
| 280 } | 269 } |
| OLD | NEW |