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 'arg_parser.dart'; | 7 import 'arg_parser.dart'; |
8 import 'arg_results.dart'; | 8 import 'arg_results.dart'; |
9 import 'option.dart'; | 9 import 'option.dart'; |
10 | 10 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 if (option == null) { | 124 if (option == null) { |
125 // Walk up to the parent command if possible. | 125 // Walk up to the parent command if possible. |
126 validate( | 126 validate( |
127 parent != null, 'Could not find an option or flag "-${soloOpt[1]}".'); | 127 parent != null, 'Could not find an option or flag "-${soloOpt[1]}".'); |
128 return parent.parseSoloOption(); | 128 return parent.parseSoloOption(); |
129 } | 129 } |
130 | 130 |
131 args.removeAt(0); | 131 args.removeAt(0); |
132 | 132 |
133 if (option.isFlag) { | 133 if (option.isFlag) { |
134 setOption(results, option, true); | 134 setFlag(results, option, true); |
135 } else { | 135 } else { |
136 readNextArgAsValue(option); | 136 readNextArgAsValue(option); |
137 } | 137 } |
138 | 138 |
139 return true; | 139 return true; |
140 } | 140 } |
141 | 141 |
142 /// Tries to parse the current argument as a series of collapsed abbreviations | 142 /// Tries to parse the current argument as a series of collapsed abbreviations |
143 /// (like "-abc") or a single abbreviation with the value directly attached | 143 /// (like "-abc") or a single abbreviation with the value directly attached |
144 /// to it (like "-mrelease"). | 144 /// to it (like "-mrelease"). |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 parent != null, 'Could not find an option with short name "-$c".'); | 189 parent != null, 'Could not find an option with short name "-$c".'); |
190 parent.parseShortFlag(c); | 190 parent.parseShortFlag(c); |
191 return; | 191 return; |
192 } | 192 } |
193 | 193 |
194 // In a list of short options, only the first can be a non-flag. If | 194 // In a list of short options, only the first can be a non-flag. If |
195 // we get here we've checked that already. | 195 // we get here we've checked that already. |
196 validate( | 196 validate( |
197 option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); | 197 option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); |
198 | 198 |
199 setOption(results, option, true); | 199 setFlag(results, option, true); |
200 } | 200 } |
201 | 201 |
202 /// Tries to parse the current argument as a long-form named option, which | 202 /// Tries to parse the current argument as a long-form named option, which |
203 /// may include a value like "--mode=release" or "--mode release". | 203 /// may include a value like "--mode=release" or "--mode release". |
204 bool parseLongOption() { | 204 bool parseLongOption() { |
205 var longOpt = _LONG_OPT.firstMatch(current); | 205 var longOpt = _LONG_OPT.firstMatch(current); |
206 if (longOpt == null) return false; | 206 if (longOpt == null) return false; |
207 | 207 |
208 var name = longOpt[1]; | 208 var name = longOpt[1]; |
209 var option = grammar.options[name]; | 209 var option = grammar.options[name]; |
210 if (option != null) { | 210 if (option != null) { |
211 args.removeAt(0); | 211 args.removeAt(0); |
212 if (option.isFlag) { | 212 if (option.isFlag) { |
213 validate(longOpt[3] == null, | 213 validate(longOpt[3] == null, |
214 'Flag option "$name" should not be given a value.'); | 214 'Flag option "$name" should not be given a value.'); |
215 | 215 |
216 setOption(results, option, true); | 216 setFlag(results, option, true); |
217 } else if (longOpt[3] != null) { | 217 } else if (longOpt[3] != null) { |
218 // We have a value like --foo=bar. | 218 // We have a value like --foo=bar. |
219 setOption(results, option, longOpt[3]); | 219 setOption(results, option, longOpt[3]); |
220 } else { | 220 } else { |
221 // Option like --foo, so look for the value as the next arg. | 221 // Option like --foo, so look for the value as the next arg. |
222 readNextArgAsValue(option); | 222 readNextArgAsValue(option); |
223 } | 223 } |
224 } else if (name.startsWith('no-')) { | 224 } else if (name.startsWith('no-')) { |
225 // See if it's a negated flag. | 225 // See if it's a negated flag. |
226 name = name.substring('no-'.length); | 226 name = name.substring('no-'.length); |
227 option = grammar.options[name]; | 227 option = grammar.options[name]; |
228 if (option == null) { | 228 if (option == null) { |
229 // Walk up to the parent command if possible. | 229 // Walk up to the parent command if possible. |
230 validate(parent != null, 'Could not find an option named "$name".'); | 230 validate(parent != null, 'Could not find an option named "$name".'); |
231 return parent.parseLongOption(); | 231 return parent.parseLongOption(); |
232 } | 232 } |
233 | 233 |
234 args.removeAt(0); | 234 args.removeAt(0); |
235 validate(option.isFlag, 'Cannot negate non-flag option "$name".'); | 235 validate(option.isFlag, 'Cannot negate non-flag option "$name".'); |
236 validate(option.negatable, 'Cannot negate option "$name".'); | 236 validate(option.negatable, 'Cannot negate option "$name".'); |
237 | 237 |
238 setOption(results, option, false); | 238 setFlag(results, option, false); |
239 } else { | 239 } else { |
240 // Walk up to the parent command if possible. | 240 // Walk up to the parent command if possible. |
241 validate(parent != null, 'Could not find an option named "$name".'); | 241 validate(parent != null, 'Could not find an option named "$name".'); |
242 return parent.parseLongOption(); | 242 return parent.parseLongOption(); |
243 } | 243 } |
244 | 244 |
245 return true; | 245 return true; |
246 } | 246 } |
247 | 247 |
248 /// Called during parsing to validate the arguments. | 248 /// Called during parsing to validate the arguments. |
249 /// | 249 /// |
250 /// Throws a [FormatException] if [condition] is `false`. | 250 /// Throws a [FormatException] if [condition] is `false`. |
251 void validate(bool condition, String message) { | 251 void validate(bool condition, String message) { |
252 if (!condition) throw new FormatException(message); | 252 if (!condition) throw new FormatException(message); |
253 } | 253 } |
254 | 254 |
255 /// Validates and stores [value] as the value for [option]. | 255 /// Validates and stores [value] as the value for [option], which must not be |
256 void setOption(Map results, Option option, value) { | 256 /// a flag. |
257 // See if it's one of the allowed values. | 257 void setOption(Map results, Option option, String value) { |
258 if (option.allowed != null) { | 258 assert(!option.isFlag); |
259 validate(option.allowed.any((allow) => allow == value), | 259 |
260 '"$value" is not an allowed value for option "${option.name}".'); | 260 if (!option.isMultiple) { |
| 261 _validateAllowed(option, value); |
| 262 results[option.name] = value; |
| 263 return; |
261 } | 264 } |
262 | 265 |
263 if (option.isMultiple) { | 266 var list = results.putIfAbsent(option.name, () => []); |
264 var list = results.putIfAbsent(option.name, () => []); | 267 |
| 268 if (option.splitCommas) { |
| 269 for (var element in value.split(",")) { |
| 270 _validateAllowed(option, element); |
| 271 list.add(element); |
| 272 } |
| 273 } else { |
| 274 _validateAllowed(option, value); |
265 list.add(value); | 275 list.add(value); |
266 } else { | |
267 results[option.name] = value; | |
268 } | 276 } |
269 } | 277 } |
| 278 |
| 279 /// Validates and stores [value] as the value for [option], which must be a |
| 280 /// flag. |
| 281 void setFlag(Map results, Option option, bool value) { |
| 282 assert(option.isFlag); |
| 283 results[option.name] = value; |
| 284 } |
| 285 |
| 286 /// Validates that [value] is allowed as a value of [option]. |
| 287 void _validateAllowed(Option option, String value) { |
| 288 if (option.allowed == null) return; |
| 289 |
| 290 validate(option.allowed.contains(value), |
| 291 '"$value" is not an allowed value for option "${option.name}".'); |
| 292 } |
270 } | 293 } |
OLD | NEW |