Print command help for "bin --help command" (#55)
Closes #54
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 108d60e..9127332 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.13.6+1
+
+* When a `CommandRunner` is passed `--help` before any commands, it now prints
+ the usage of the chosen command.
+
## 0.13.6
* `ArgParser.parse()` now throws an `ArgParserException`, which implements
diff --git a/lib/command_runner.dart b/lib/command_runner.dart
index fa22c23..338ad94 100644
--- a/lib/command_runner.dart
+++ b/lib/command_runner.dart
@@ -133,56 +133,59 @@
/// It's useful to override this to handle global flags and/or wrap the entire
/// command in a block. For example, you might handle the `--verbose` flag
/// here to enable verbose logging before running the command.
- Future runCommand(ArgResults topLevelResults) {
- return new Future.sync(() {
- var argResults = topLevelResults;
- var commands = _commands;
- Command command;
- var commandString = executableName;
+ Future runCommand(ArgResults topLevelResults) async {
+ var argResults = topLevelResults;
+ var commands = _commands;
+ Command command;
+ var commandString = executableName;
- while (commands.isNotEmpty) {
- if (argResults.command == null) {
- if (argResults.rest.isEmpty) {
- if (command == null) {
- // No top-level command was chosen.
- printUsage();
- return new Future.value();
- }
-
- command.usageException('Missing subcommand for "$commandString".');
- } else {
- if (command == null) {
- usageException(
- 'Could not find a command named "${argResults.rest[0]}".');
- }
-
- command.usageException('Could not find a subcommand named '
- '"${argResults.rest[0]}" for "$commandString".');
+ while (commands.isNotEmpty) {
+ if (argResults.command == null) {
+ if (argResults.rest.isEmpty) {
+ if (command == null) {
+ // No top-level command was chosen.
+ printUsage();
+ return;
}
- }
- // Step into the command.
- argResults = argResults.command;
- command = commands[argResults.name];
- command._globalResults = topLevelResults;
- command._argResults = argResults;
- commands = command._subcommands;
- commandString += " ${argResults.name}";
+ command.usageException('Missing subcommand for "$commandString".');
+ } else {
+ if (command == null) {
+ usageException(
+ 'Could not find a command named "${argResults.rest[0]}".');
+ }
- if (argResults['help']) {
- command.printUsage();
- return new Future.value();
+ command.usageException('Could not find a subcommand named '
+ '"${argResults.rest[0]}" for "$commandString".');
}
}
- // Make sure there aren't unexpected arguments.
- if (!command.takesArguments && argResults.rest.isNotEmpty) {
- command.usageException(
- 'Command "${argResults.name}" does not take any arguments.');
- }
+ // Step into the command.
+ argResults = argResults.command;
+ command = commands[argResults.name];
+ command._globalResults = topLevelResults;
+ command._argResults = argResults;
+ commands = command._subcommands;
+ commandString += " ${argResults.name}";
- return command.run();
- });
+ if (argResults['help']) {
+ command.printUsage();
+ return;
+ }
+ }
+
+ if (topLevelResults['help']) {
+ command.printUsage();
+ return;
+ }
+
+ // Make sure there aren't unexpected arguments.
+ if (!command.takesArguments && argResults.rest.isNotEmpty) {
+ command.usageException(
+ 'Command "${argResults.name}" does not take any arguments.');
+ }
+
+ await command.run();
}
}
@@ -275,8 +278,8 @@
/// Returns [usage] with [description] removed from the beginning.
String get _usageWithoutDescription {
var buffer = new StringBuffer()
- ..writeln('Usage: $invocation')
- ..writeln(argParser.usage);
+ ..writeln('Usage: $invocation')
+ ..writeln(argParser.usage);
if (_subcommands.isNotEmpty) {
buffer.writeln();
@@ -362,7 +365,7 @@
/// Throws a [UsageException] with [message].
void usageException(String message) =>
- throw new UsageException(message, _usageWithoutDescription);
+ throw new UsageException(message, _usageWithoutDescription);
}
/// Returns a string representation of [commands] fit for use in a usage string.
@@ -373,7 +376,7 @@
{bool isSubcommand: false}) {
// Don't include aliases.
var names =
- commands.keys.where((name) => !commands[name].aliases.contains(name));
+ commands.keys.where((name) => !commands[name].aliases.contains(name));
// Filter out hidden ones, unless they are all hidden.
var visible = names.where((name) => !commands[name].hidden);
@@ -384,7 +387,7 @@
var length = names.map((name) => name.length).reduce(math.max);
var buffer =
- new StringBuffer('Available ${isSubcommand ? "sub" : ""}commands:');
+ new StringBuffer('Available ${isSubcommand ? "sub" : ""}commands:');
for (var name in names) {
var lines = commands[name].summary.split("\n");
buffer.writeln();
diff --git a/pubspec.yaml b/pubspec.yaml
index ab921a5..4156049 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: args
-version: 0.13.6
+version: 0.13.6+1
author: "Dart Team <misc@dartlang.org>"
homepage: https://github.com/dart-lang/args
description: >
diff --git a/test/command_runner_test.dart b/test/command_runner_test.dart
index 6b4e30e..8875d8c 100644
--- a/test/command_runner_test.dart
+++ b/test/command_runner_test.dart
@@ -197,7 +197,7 @@
"""));
});
- test("with a command prints the usage for that command", () {
+ test("with a preceding command prints the usage for that command", () {
var command = new FooCommand();
runner.addCommand(command);
@@ -210,6 +210,20 @@
Run "test help" to see global options.
"""));
});
+
+ test("with a following command prints the usage for that command", () {
+ var command = new FooCommand();
+ runner.addCommand(command);
+
+ expect(() => runner.run(["--help", "foo"]), prints("""
+Set a value.
+
+Usage: test foo [arguments]
+-h, --help Print this usage information.
+
+Run "test help" to see global options.
+"""));
+ });
});
group("with help command", () {