| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| /// Creates a new [Option]. | |
| /// | |
| /// Since [Option] doesn't have a public constructor, this lets `ArgParser` | |
| /// get to it. This function isn't exported to the public API of the package. | |
| Option newOption( | |
| String name, | |
| String? abbr, | |
| String? help, | |
| String? valueHelp, | |
| Iterable<String>? allowed, | |
| Map<String, String>? allowedHelp, | |
| Object? defaultsTo, | |
| Function? callback, | |
| OptionType type, | |
| {bool? negatable, | |
| bool? splitCommas, | |
| bool mandatory = false, | |
| bool hide = false, | |
| bool hideNegatedUsage = false, | |
| List<String> aliases = const []}) { | |
| return Option._(name, abbr, help, valueHelp, allowed, allowedHelp, defaultsTo, | |
| callback, type, | |
| negatable: negatable, | |
| splitCommas: splitCommas, | |
| mandatory: mandatory, | |
| hide: hide, | |
| hideNegatedUsage: hideNegatedUsage, | |
| aliases: aliases); | |
| } | |
| /// A command-line option. | |
| /// | |
| /// This represents both boolean flags and options which take a value. | |
| class Option { | |
| /// The name of the option that the user passes as an argument. | |
| final String name; | |
| /// A single-character string that can be used as a shorthand for this option. | |
| /// | |
| /// For example, `abbr: "a"` will allow the user to pass `-a value` or | |
| /// `-avalue`. | |
| final String? abbr; | |
| /// A description of this option. | |
| final String? help; | |
| /// A name for the value this option takes. | |
| final String? valueHelp; | |
| /// A list of valid values for this option. | |
| final List<String>? allowed; | |
| /// A map from values in [allowed] to documentation for those values. | |
| final Map<String, String>? allowedHelp; | |
| /// The value this option will have if the user doesn't explicitly pass it. | |
| final dynamic defaultsTo; | |
| /// Whether this flag's value can be set to `false`. | |
| /// | |
| /// For example, if [name] is `flag`, the user can pass `--no-flag` to set its | |
| /// value to `false`. | |
| /// | |
| /// This is `null` unless [type] is [OptionType.flag]. | |
| final bool? negatable; | |
| /// Whether to document that this flag is [negatable]. | |
| /// | |
| /// This is `null` unless [type] is [OptionType.flag]. | |
| final bool? hideNegatedUsage; | |
| /// The callback to invoke with the option's value when the option is parsed. | |
| final Function? callback; | |
| /// Whether this is a flag, a single value option, or a multi-value option. | |
| final OptionType type; | |
| /// Whether multiple values may be passed by writing `--option a,b` in | |
| /// addition to `--option a --option b`. | |
| final bool splitCommas; | |
| /// Whether this option must be provided for correct usage. | |
| final bool mandatory; | |
| /// Whether this option should be hidden from usage documentation. | |
| final bool hide; | |
| /// All aliases for [name]. | |
| final List<String> aliases; | |
| /// Whether the option is boolean-valued flag. | |
| bool get isFlag => type == OptionType.flag; | |
| /// Whether the option takes a single value. | |
| bool get isSingle => type == OptionType.single; | |
| /// Whether the option allows multiple values. | |
| bool get isMultiple => type == OptionType.multiple; | |
| Option._( | |
| this.name, | |
| this.abbr, | |
| this.help, | |
| this.valueHelp, | |
| Iterable<String>? allowed, | |
| Map<String, String>? allowedHelp, | |
| this.defaultsTo, | |
| this.callback, | |
| this.type, | |
| {this.negatable, | |
| bool? splitCommas, | |
| this.mandatory = false, | |
| this.hide = false, | |
| this.hideNegatedUsage, | |
| this.aliases = const []}) | |
| : allowed = allowed == null ? null : List.unmodifiable(allowed), | |
| allowedHelp = | |
| allowedHelp == null ? null : Map.unmodifiable(allowedHelp), | |
| // If the user doesn't specify [splitCommas], it defaults to true for | |
| // multiple options. | |
| splitCommas = splitCommas ?? type == OptionType.multiple { | |
| if (name.isEmpty) { | |
| throw ArgumentError('Name cannot be empty.'); | |
| } else if (name.startsWith('-')) { | |
| throw ArgumentError('Name $name cannot start with "-".'); | |
| } | |
| // Ensure name does not contain any invalid characters. | |
| if (_invalidChars.hasMatch(name)) { | |
| throw ArgumentError('Name "$name" contains invalid characters.'); | |
| } | |
| var abbr = this.abbr; | |
| if (abbr != null) { | |
| if (abbr.length != 1) { | |
| throw ArgumentError('Abbreviation must be null or have length 1.'); | |
| } else if (abbr == '-') { | |
| throw ArgumentError('Abbreviation cannot be "-".'); | |
| } | |
| if (_invalidChars.hasMatch(abbr)) { | |
| throw ArgumentError('Abbreviation is an invalid character.'); | |
| } | |
| } | |
| } | |
| /// Returns [value] if non-`null`, otherwise returns the default value for | |
| /// this option. | |
| /// | |
| /// For single-valued options, it will be [defaultsTo] if set or `null` | |
| /// otherwise. For multiple-valued options, it will be an empty list or a | |
| /// list containing [defaultsTo] if set. | |
| dynamic valueOrDefault(Object? value) { | |
| if (value != null) return value; | |
| if (isMultiple) return defaultsTo ?? <String>[]; | |
| return defaultsTo; | |
| } | |
| @Deprecated('Use valueOrDefault instead.') | |
| dynamic getOrDefault(Object? value) => valueOrDefault(value); | |
| static final _invalidChars = RegExp(r'''[ \t\r\n"'\\/]'''); | |
| } | |
| /// What kinds of values an option accepts. | |
| class OptionType { | |
| /// An option that can only be `true` or `false`. | |
| /// | |
| /// The presence of the option name itself in the argument list means `true`. | |
| static const flag = OptionType._('OptionType.flag'); | |
| /// An option that takes a single value. | |
| /// | |
| /// Examples: | |
| /// | |
| /// --mode debug | |
| /// -mdebug | |
| /// --mode=debug | |
| /// | |
| /// If the option is passed more than once, the last one wins. | |
| static const single = OptionType._('OptionType.single'); | |
| /// An option that allows multiple values. | |
| /// | |
| /// Example: | |
| /// | |
| /// --output text --output xml | |
| /// | |
| /// In the parsed `ArgResults`, a multiple-valued option will always return | |
| /// a list, even if one or no values were passed. | |
| static const multiple = OptionType._('OptionType.multiple'); | |
| final String name; | |
| const OptionType._(this.name); | |
| } |