Chromium Code Reviews

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

Issue 12472019: pkg/args Option should be more strict about names and abbreviations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/args/test/args_test.dart » ('j') | pkg/args/test/args_test.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /** 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 * ## Defining options ## 9 * ## Defining options ##
10 * 10 *
(...skipping 267 matching lines...)
278 Map<String, String> allowedHelp, defaultsTo, 278 Map<String, String> allowedHelp, defaultsTo,
279 void callback(value), {bool isFlag, bool negatable: false, 279 void callback(value), {bool isFlag, bool negatable: false,
280 bool allowMultiple: false}) { 280 bool allowMultiple: false}) {
281 // Make sure the name isn't in use. 281 // Make sure the name isn't in use.
282 if (options.containsKey(name)) { 282 if (options.containsKey(name)) {
283 throw new ArgumentError('Duplicate option "$name".'); 283 throw new ArgumentError('Duplicate option "$name".');
284 } 284 }
285 285
286 // Make sure the abbreviation isn't too long or in use. 286 // Make sure the abbreviation isn't too long or in use.
287 if (abbr != null) { 287 if (abbr != null) {
288 if (abbr.length > 1) {
289 throw new ArgumentError(
290 'Abbreviation "$abbr" is longer than one character.');
291 }
292
293 var existing = findByAbbreviation(abbr); 288 var existing = findByAbbreviation(abbr);
294 if (existing != null) { 289 if (existing != null) {
295 throw new ArgumentError( 290 throw new ArgumentError(
296 'Abbreviation "$abbr" is already used by "${existing.name}".'); 291 'Abbreviation "$abbr" is already used by "${existing.name}".');
297 } 292 }
298 } 293 }
299 294
300 options[name] = new Option(name, abbr, help, allowed, allowedHelp, 295 options[name] = new Option(name, abbr, help, allowed, allowedHelp,
301 defaultsTo, callback, isFlag: isFlag, negatable: negatable, 296 defaultsTo, callback, isFlag: isFlag, negatable: negatable,
302 allowMultiple: allowMultiple); 297 allowMultiple: allowMultiple);
(...skipping 32 matching lines...)
335 orElse: () => null); 330 orElse: () => null);
336 } 331 }
337 } 332 }
338 333
339 /** 334 /**
340 * A command-line option. Includes both flags and options which take a value. 335 * A command-line option. Includes both flags and options which take a value.
341 */ 336 */
342 class Option { 337 class Option {
343 final String name; 338 final String name;
344 final String abbreviation; 339 final String abbreviation;
345 final List allowed; 340 final List<String> allowed;
346 final defaultValue; 341 final defaultValue;
347 final Function callback; 342 final Function callback;
348 final String help; 343 final String help;
349 final Map<String, String> allowedHelp; 344 final Map<String, String> allowedHelp;
350 final bool isFlag; 345 final bool isFlag;
351 final bool negatable; 346 final bool negatable;
352 final bool allowMultiple; 347 final bool allowMultiple;
353 348
354 Option(this.name, this.abbreviation, this.help, this.allowed, 349 Option(this.name, this.abbreviation, this.help, this.allowed,
355 this.allowedHelp, this.defaultValue, this.callback, {this.isFlag, 350 this.allowedHelp, this.defaultValue, this.callback, {this.isFlag,
356 this.negatable, this.allowMultiple: false}); 351 this.negatable, this.allowMultiple: false}) {
352 if(name == null) {
Bob Nystrom 2013/03/13 18:07:09 Space between keyword and "(" here and elsewhere (
353 throw new ArgumentError('"name" cannot be null');
Bob Nystrom 2013/03/13 18:07:09 As dumb as it seems, almost all Dart code I've see
354 } else if(name.isEmpty) {
355 throw new ArgumentError('"name" cannot be empty');
Bob Nystrom 2013/03/13 18:07:09 The quoting here is confusing. How about "Name can
356 } else if(name.startsWith('-')) {
357 throw new ArgumentError('"name" cannot start with "-"');
Bob Nystrom 2013/03/13 18:07:09 Would be nice to show the offending argument: 'Nam
358 }
359
360 // ensure name does not contain any invalid characters
Bob Nystrom 2013/03/13 18:07:09 Sentence capitalize and add a ".".
361 for(final char in _invalidChars) {
Bob Nystrom 2013/03/13 18:07:09 This seems like a good case for a regexp: if (_in
362 if(name.contains(char)) {
363 throw new ArgumentError('"name" contains invalid characters');
364 }
365 if(name.contains(char)) {
366 throw new ArgumentError('"name" contains invalid characters');
367 }
368 }
369
370 if(abbreviation != null) {
371 if(abbreviation.length != 1) {
372 throw new ArgumentError('"abbreviation" must be null or have length 1');
373 } else if(abbreviation == '-') {
374 throw new ArgumentError('"abbreviation" cannot be "-"');
375 }
376
377 for(final char in _invalidChars) {
378 if(abbreviation.contains(char)) {
379 throw new ArgumentError('"abbreviation" is an invalid valid');
Bob Nystrom 2013/03/13 18:07:09 This error message is a little odd. :)
380 }
381 }
382 }
383 }
384
385 const _invalidChars = const [' ', '\t', '\r', '\n', '"', '"', r'\', r'/'];
Bob Nystrom 2013/03/13 18:07:09 Since it isn't instance-specific and is private, h
kevmoo-old 2013/03/13 19:35:53 My theory: since it's *only* used by the class, we
357 } 386 }
358 387
359 /** 388 /**
360 * The results of parsing a series of command line arguments using 389 * The results of parsing a series of command line arguments using
361 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed 390 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed
362 * command line arguments. 391 * command line arguments.
363 */ 392 */
364 class ArgResults { 393 class ArgResults {
365 final Map _options; 394 final Map _options;
366 395
(...skipping 26 matching lines...)
393 'Could not find an option named "$name".'); 422 'Could not find an option named "$name".');
394 } 423 }
395 424
396 return _options[name]; 425 return _options[name];
397 } 426 }
398 427
399 /** Get the names of the options as a [Collection]. */ 428 /** Get the names of the options as a [Collection]. */
400 Collection<String> get options => _options.keys.toList(growable: false); 429 Collection<String> get options => _options.keys.toList(growable: false);
401 } 430 }
402 431
OLDNEW
« no previous file with comments | « no previous file | pkg/args/test/args_test.dart » ('j') | pkg/args/test/args_test.dart » ('J')

Powered by Google App Engine