Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce new typed ArgResults flag(String), option(String), and multiOption(String) methods #248

Merged
merged 10 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.5.0-wip

* Introduce new typed `ArgResults` `flag(String)`, `option(String)`, and
`multiOption(String)` methods.

## 2.4.2

* Change the validation of `mandatory` options; they now perform validation when
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ parser.addOption('mode');
parser.addFlag('verbose', defaultsTo: true);
var results = parser.parse(['--mode', 'debug', 'something', 'else']);

print(results['mode']); // debug
print(results['verbose']); // true
print(results.option('mode')); // debug
print(results.flag('verbose')); // true
```

By default, the `parse()` method allows additional flags and options to be
Expand Down Expand Up @@ -187,7 +187,7 @@ overriding earlier ones; for example:
var parser = ArgParser();
parser.addOption('mode');
var results = parser.parse(['--mode', 'on', '--mode', 'off']);
print(results['mode']); // prints 'off'
print(results.option('mode')); // prints 'off'
```

Multiple values can be parsed with `addMultiOption()`. With this method, an
Expand All @@ -198,7 +198,7 @@ values:
var parser = ArgParser();
parser.addMultiOption('mode');
var results = parser.parse(['--mode', 'on', '--mode', 'off']);
print(results['mode']); // prints '[on, off]'
print(results.multiOption('mode')); // prints '[on, off]'
```

By default, values for a multi-valued option may also be separated with commas:
Expand All @@ -207,7 +207,7 @@ By default, values for a multi-valued option may also be separated with commas:
var parser = ArgParser();
parser.addMultiOption('mode');
var results = parser.parse(['--mode', 'on,off']);
print(results['mode']); // prints '[on, off]'
print(results.multiOption('mode')); // prints '[on, off]'
```

This can be disabled by passing `splitCommas: false`.
Expand Down Expand Up @@ -325,7 +325,7 @@ class CommitCommand extends Command {
void run() {
// [argResults] is set before [run()] is called and contains the flags/options
// passed to this command.
print(argResults['all']);
print(argResults.flag('all'));
}
}
```
Expand Down
18 changes: 9 additions & 9 deletions example/command_runner/draw.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class SquareCommand extends Command<String> {

@override
FutureOr<String>? run() {
final size = int.parse(argResults?['size'] as String? ?? '20');
final char = (globalResults?['char'] as String?)?[0] ?? '#';
final size = int.parse(argResults.option('size') ?? '20');
final char = globalResults?.option('char')?[0] ?? '#';
return draw(size, size, char, (x, y) => true);
}
}
Expand All @@ -55,8 +55,8 @@ class CircleCommand extends Command<String> {

@override
FutureOr<String>? run() {
final size = 2 * int.parse(argResults?['radius'] as String? ?? '10');
final char = (globalResults?['char'] as String?)?[0] ?? '#';
final size = 2 * int.parse(argResults.option('radius') ?? '10');
final char = globalResults?.option('char')?[0] ?? '#';
return draw(size, size, char, (x, y) => x * x + y * y < 1);
}
}
Expand Down Expand Up @@ -93,8 +93,8 @@ class EquilateralTriangleCommand extends Command<String> {

@override
FutureOr<String>? run() {
final size = int.parse(argResults?['size'] as String? ?? '20');
final char = (globalResults?['char'] as String?)?[0] ?? '#';
final size = int.parse(argResults.option('size') ?? '20');
final char = globalResults?.option('char')?[0] ?? '#';
return drawTriangle(size, size * sqrt(3) ~/ 2, char);
}
}
Expand All @@ -116,9 +116,9 @@ class IsoscelesTriangleCommand extends Command<String> {

@override
FutureOr<String>? run() {
final width = int.parse(argResults?['width'] as String? ?? '50');
final height = int.parse(argResults?['height'] as String? ?? '10');
final char = (globalResults?['char'] as String?)?[0] ?? '#';
final width = int.parse(argResults.option('width') ?? '50');
final height = int.parse(argResults.option('height') ?? '10');
final char = globalResults?.option('char')?[0] ?? '#';
return drawTriangle(width, height, char);
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ class CommandRunner<T> {
commands = command._subcommands as Map<String, Command<T>>;
commandString += ' ${argResults.name}';

if (argResults.options.contains('help') && (argResults['help'] as bool)) {
if (argResults.options.contains('help') && argResults.flag('help')) {
command.printUsage();
return null;
}
}

if (topLevelResults['help'] as bool) {
if (topLevelResults.flag('help')) {
command!.printUsage();
return null;
}
Expand Down Expand Up @@ -320,7 +320,7 @@ abstract class Command<T> {
/// The parsed argument results for this command.
///
/// This will be `null` until just before [Command.run] is called.
devoncarew marked this conversation as resolved.
Show resolved Hide resolved
ArgResults? get argResults => _argResults;
ArgResults get argResults => _argResults!;
devoncarew marked this conversation as resolved.
Show resolved Hide resolved
ArgResults? _argResults;

/// The argument parser for this command.
Expand Down
49 changes: 47 additions & 2 deletions lib/src/arg_results.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ArgResults newArgResults(
}

/// The results of parsing a series of command line arguments using
/// [ArgParser.parse()].
/// [ArgParser.parse].
///
/// Includes the parsed options and any remaining unparsed command line
/// arguments.
Expand Down Expand Up @@ -57,7 +57,7 @@ class ArgResults {
: rest = UnmodifiableListView(rest),
arguments = UnmodifiableListView(arguments);

/// Returns the parsed ore default command-line option named [name].
/// Returns the parsed or default command-line option named [name].
///
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we deprecate this? Or at least mention the new alternatives here in the dartdoc?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mark it deprecated (or at least not yet), but I like the idea of having the doc comment here point to the new better methods.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was a little hesitant about deprecating it given that essentially every user of this package will get deprecation messages.

Updating the docs here make sense.

Copy link
Member Author

@devoncarew devoncarew Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  /// > [!Note]
  /// > Callers should prefer using the more strongly typed methods - [flag] for
  /// > flags, [option] for options, and [multiOption] for multi-options.

/// [name] must be a valid option name in the parser.
dynamic operator [](String name) {
Expand All @@ -73,6 +73,51 @@ class ArgResults {
return option.valueOrDefault(_parsed[name]);
}

/// Returns the parsed or default command-line flag named [name].
///
/// [name] must be a valid flag name in the parser.
bool flag(String name) {
if (!_parser.options.containsKey(name)) {
throw ArgumentError('Could not find an option named "$name".');
}

var option = _parser.options[name]!;
devoncarew marked this conversation as resolved.
Show resolved Hide resolved
if (!option.isFlag) {
throw ArgumentError('"$name" is not a flag.');
}
return option.valueOrDefault(_parsed[name]) as bool;
}

/// Returns the parsed or default command-line option named [name].
///
/// [name] must be a valid option name in the parser.
String? option(String name) {
if (!_parser.options.containsKey(name)) {
throw ArgumentError('Could not find an option named "$name".');
}

var option = _parser.options[name]!;
if (!option.isSingle) {
throw ArgumentError('"$name" is not an option.');
}
return option.valueOrDefault(_parsed[name]) as String?;
}

/// Returns the list of parsed (or default) command-line options for [name].
///
/// [name] must be a valid option name in the parser.
List<String> multiOption(String name) {
if (!_parser.options.containsKey(name)) {
throw ArgumentError('Could not find an option named "$name".');
}

var option = _parser.options[name]!;
if (!option.isMultiple) {
throw ArgumentError('"$name" is not a multi-option.');
}
return option.valueOrDefault(_parsed[name]) as List<String>;
}

/// The names of the available options.
///
/// Includes the options whose values were parsed or that have defaults.
Expand Down
4 changes: 2 additions & 2 deletions lib/src/help_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class HelpCommand<T> extends Command<T> {
@override
Null run() {
// Show the default help if no command was specified.
if (argResults!.rest.isEmpty) {
if (argResults.rest.isEmpty) {
runner!.printUsage();
return;
}
Expand All @@ -35,7 +35,7 @@ class HelpCommand<T> extends Command<T> {
Command<T>? command;
var commandString = runner!.executableName;

for (var name in argResults!.rest) {
for (var name in argResults.rest) {
if (commands.isEmpty) {
command!.usageException(
'Command "$commandString" does not expect a subcommand.');
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: args
version: 2.4.2
version: 2.5.0-wip
description: >-
Library for defining parsers for parsing raw command-line arguments into a set
of options and values using GNU and POSIX style options.
Library for defining parsers for parsing raw command-line arguments into a set
of options and values using GNU and POSIX style options.
repository: https://github.com/dart-lang/args

topics:
Expand Down
2 changes: 1 addition & 1 deletion test/command_runner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -755,5 +755,5 @@ class _MandatoryOptionCommand extends Command {
String get name => 'mandatory-option-command';

@override
String run() => argResults!['mandatory-option'] as String;
String run() => argResults['mandatory-option'] as String;
}
Loading