Tweak the new word wrapping and get ready to release it.
- Renamed "maxLineLength" to "usageLineLength". In the context of
ArgParser, the former makes it sound like it's the argument line
itself that it applies to.
- Some style tweaks.
- Remove some ooooold workarounds. Strings support padRight() now.
- Run dartfmt on it.
- Bump the version number and update CHANGELOG.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d418df9..f1e947c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.4.5
+
+* Add `usageLineLength` to control word wrapping usage text.
+
## 1.4.4
* Set max SDK version to `<3.0.0`, and adjust other dependencies.
diff --git a/lib/src/allow_anything_parser.dart b/lib/src/allow_anything_parser.dart
index 34a0b19..31215ba 100644
--- a/lib/src/allow_anything_parser.dart
+++ b/lib/src/allow_anything_parser.dart
@@ -13,7 +13,7 @@
Map<String, ArgParser> get commands => const {};
bool get allowTrailingOptions => false;
bool get allowsAnything => true;
- int get maxLineLength => null;
+ int get usageLineLength => null;
ArgParser addCommand(String name, [ArgParser parser]) {
throw new UnsupportedError(
diff --git a/lib/src/arg_parser.dart b/lib/src/arg_parser.dart
index a25a8b8..cdc54e6 100644
--- a/lib/src/arg_parser.dart
+++ b/lib/src/arg_parser.dart
@@ -40,7 +40,7 @@
/// there is no whitespace at which to split).
///
/// If null (the default), help messages are not wrapped.
- final int maxLineLength;
+ final int usageLineLength;
/// Whether or not this parser treats unrecognized options as non-option
/// arguments.
@@ -52,10 +52,10 @@
/// flags and options that appear after positional arguments. If it's `false`,
/// the parser stops parsing as soon as it finds an argument that is neither
/// an option nor a command.
- factory ArgParser({bool allowTrailingOptions: true, int maxLineLength}) =>
+ factory ArgParser({bool allowTrailingOptions: true, int usageLineLength}) =>
new ArgParser._(<String, Option>{}, <String, ArgParser>{},
allowTrailingOptions: allowTrailingOptions,
- maxLineLength: maxLineLength);
+ usageLineLength: usageLineLength);
/// Creates a new ArgParser that treats *all input* as non-option arguments.
///
@@ -66,7 +66,7 @@
factory ArgParser.allowAnything() = AllowAnythingParser;
ArgParser._(Map<String, Option> options, Map<String, ArgParser> commands,
- {bool allowTrailingOptions: true, this.maxLineLength})
+ {bool allowTrailingOptions: true, this.usageLineLength})
: this._options = options,
this.options = new UnmodifiableMapView(options),
this._commands = commands,
@@ -329,7 +329,7 @@
///
/// This is basically the help text shown on the command line.
String get usage {
- return new Usage(_optionsAndSeparators, maxLineLength: maxLineLength)
+ return new Usage(_optionsAndSeparators, lineLength: usageLineLength)
.generate();
}
diff --git a/lib/src/usage.dart b/lib/src/usage.dart
index cc84e6c..1135bb5 100644
--- a/lib/src/usage.dart
+++ b/lib/src/usage.dart
@@ -2,7 +2,7 @@
// 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.
-import 'dart:math';
+import 'dart:math' as math;
import '../args.dart';
@@ -18,7 +18,8 @@
/// It builds the usage text up one column at a time and handles padding with
/// spaces and wrapping to the next line to keep the cells correctly lined up.
class Usage {
- static const NUM_COLUMNS = 3; // Abbreviation, long name, help.
+ /// Abbreviation, long name, help.
+ static const _columnCount = 3;
/// A list of the [Option]s intermingled with [String] separators.
final List optionsAndSeparators;
@@ -54,9 +55,9 @@
/// The horizontal character position at which help text is wrapped. Help that
/// extends past this column will be wrapped at the nearest whitespace (or
/// truncated if there is no available whitespace).
- final int maxLineLength;
+ final int lineLength;
- Usage(this.optionsAndSeparators, {this.maxLineLength});
+ Usage(this.optionsAndSeparators, {this.lineLength});
/// Generates a string displaying usage information for the defined options.
/// This is basically the help text shown on the command line.
@@ -152,15 +153,15 @@
if (option.hide) continue;
// Make room in the first column if there are abbreviations.
- abbr = max(abbr, getAbbreviation(option).length);
+ abbr = math.max(abbr, getAbbreviation(option).length);
// Make room for the option.
- title = max(title, getLongOption(option).length);
+ title = math.max(title, getLongOption(option).length);
// Make room for the allowed help.
if (option.allowedHelp != null) {
for (var allowed in option.allowedHelp.keys) {
- title = max(title, getAllowedTitle(option, allowed).length);
+ title = math.max(title, getAllowedTitle(option, allowed).length);
}
}
}
@@ -176,38 +177,40 @@
numHelpLines = 0;
}
- // Wrap a single line of text into lines no longer than maxLineLength,
- // starting at the "start" column.
- // Try to split at whitespace, but if that's not good enough to keep it
- // under the maxLineLength, then split in the middle of a word.
+ /// Wraps a single line of text into lines no longer than [lineLength],
+ /// starting at the [start] column.
+ ///
+ /// Tries to split at whitespace, but if that's not good enough to keep it
+ /// under the limit, then splits in the middle of a word.
List<String> _wrap(String text, int start) {
assert(start >= 0);
- const int minColumnWidth = 10;
- final int length = max(maxLineLength - start, minColumnWidth);
+
text = text.trim();
- if (text.length <= length) {
- return [text];
- }
+
+ var length = math.max(lineLength - start, 10);
+ if (text.length <= length) return [text];
+
var result = <String>[];
- int currentLineStart = 0;
+ var currentLineStart = 0;
int lastWhitespace;
- for (int i = 0; i < text.length; ++i) {
- if (isWhitespace(text, i)) {
- lastWhitespace = i;
- }
- if ((i - currentLineStart) >= length) {
+ for (var i = 0; i < text.length; ++i) {
+ if (isWhitespace(text, i)) lastWhitespace = i;
+
+ if (i - currentLineStart >= length) {
// Back up to the last whitespace, unless there wasn't any, in which
// case we just split where we are.
- if (lastWhitespace != null) {
- i = lastWhitespace;
- }
+ if (lastWhitespace != null) i = lastWhitespace;
+
result.add(text.substring(currentLineStart, i));
+
// Skip any intervening whitespace.
while (isWhitespace(text, i) && i < text.length) i++;
+
currentLineStart = i;
lastWhitespace = null;
}
}
+
result.add(text.substring(currentLineStart));
return result;
}
@@ -215,14 +218,16 @@
void write(int column, String text) {
var lines = text.split('\n');
// If we are writing the last column, word wrap it to fit.
- if (column == columnWidths.length && maxLineLength != null) {
+ if (column == columnWidths.length && lineLength != null) {
var wrappedLines = <String>[];
- int start = columnWidths
+ var start = columnWidths
.sublist(0, column)
- .reduce((int start, int width) => start += width);
+ .reduce((start, width) => start += width);
+
for (var line in lines) {
wrappedLines.addAll(_wrap(line, start));
}
+
lines = wrappedLines;
}
@@ -250,31 +255,31 @@
// Advance until we are at the right column (which may mean wrapping around
// to the next line.
while (currentColumn != column) {
- if (currentColumn < NUM_COLUMNS - 1) {
- buffer.write(padRight('', columnWidths[currentColumn]));
+ if (currentColumn < _columnCount - 1) {
+ buffer.write(' ' * columnWidths[currentColumn]);
} else {
buffer.write('\n');
}
- currentColumn = (currentColumn + 1) % NUM_COLUMNS;
+ currentColumn = (currentColumn + 1) % _columnCount;
}
if (column < columnWidths.length) {
// Fixed-size column, so pad it.
- buffer.write(padRight(text, columnWidths[column]));
+ buffer.write(text.padRight(columnWidths[column]));
} else {
// The last column, so just write it.
buffer.write(text);
}
// Advance to the next column.
- currentColumn = (currentColumn + 1) % NUM_COLUMNS;
+ currentColumn = (currentColumn + 1) % _columnCount;
// If we reached the last column, we need to wrap to the next line.
- if (column == NUM_COLUMNS - 1) newlinesNeeded++;
+ if (column == _columnCount - 1) newlinesNeeded++;
// Keep track of how many consecutive lines we've written in the last
// column.
- if (column == NUM_COLUMNS - 1) {
+ if (column == _columnCount - 1) {
numHelpLines++;
} else {
numHelpLines = 0;
@@ -302,18 +307,6 @@
}
}
-/// Pads [source] to [length] by adding spaces at the end.
-String padRight(String source, int length) {
- final result = new StringBuffer();
- result.write(source);
-
- while (result.length < length) {
- result.write(' ');
- }
-
- return result.toString();
-}
-
bool isWhitespace(String text, int index) {
final int rune = text.codeUnitAt(index);
return rune >= 0x0009 && rune <= 0x000D ||
diff --git a/pubspec.yaml b/pubspec.yaml
index 80b6033..27583bf 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: args
-version: 1.4.4
+version: 1.4.5
author: "Dart Team <misc@dartlang.org>"
homepage: https://github.com/dart-lang/args
description: >
diff --git a/test/usage_test.dart b/test/usage_test.dart
index d7ee3dc..c556b6d 100644
--- a/test/usage_test.dart
+++ b/test/usage_test.dart
@@ -314,8 +314,8 @@
''');
});
- test("help strings are not wrapped if maxLineLength is null", () {
- var parser = new ArgParser(maxLineLength: null);
+ test("help strings are not wrapped if usageLineLength is null", () {
+ var parser = new ArgParser(usageLineLength: null);
parser.addFlag('long',
help: 'The flag with a really long help text that will not '
'be wrapped.');
@@ -324,9 +324,9 @@
''');
});
- test("help strings are wrapped properly when maxLineLength is specified",
+ test("help strings are wrapped properly when usageLineLength is specified",
() {
- var parser = new ArgParser(maxLineLength: 60);
+ var parser = new ArgParser(usageLineLength: 60);
parser.addFlag('long',
help: 'The flag with a really long help text that will be wrapped.');
parser.addFlag('longNewline',
@@ -358,9 +358,9 @@
});
test(
- "help strings are wrapped with at 10 chars when maxHelpLineLength is "
+ "help strings are wrapped with at 10 chars when usageLineLength is "
"smaller than available space", () {
- var parser = new ArgParser(maxLineLength: 1);
+ var parser = new ArgParser(usageLineLength: 1);
parser.addFlag('long',
help: 'The flag with a really long help text that will be wrapped.');
parser.addFlag('longNewline',
@@ -371,9 +371,11 @@
help:
'The-flag-with-no-whitespace-that-will-be-wrapped-by-splitting-a-word.');
parser.addFlag('longWhitespace',
- help: ' The flag with a really long help text and whitespace at the start.');
+ help:
+ ' The flag with a really long help text and whitespace at the start.');
parser.addFlag('longTrailspace',
- help: 'The flag with a really long help text and whitespace at the end. ');
+ help:
+ 'The flag with a really long help text and whitespace at the end. ');
parser.addFlag('small1', help: ' a ');
parser.addFlag('small2', help: ' a');
parser.addFlag('small3', help: 'a ');