| Index: packages/dart_style/bin/format.dart
|
| diff --git a/packages/dart_style/bin/format.dart b/packages/dart_style/bin/format.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cd97fb01593f259708cebd06f10f400b55d5585a
|
| --- /dev/null
|
| +++ b/packages/dart_style/bin/format.dart
|
| @@ -0,0 +1,216 @@
|
| +// Copyright (c) 2015, 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.
|
| +
|
| +import 'dart:convert';
|
| +import 'dart:io';
|
| +
|
| +import 'package:args/args.dart';
|
| +import 'package:dart_style/src/dart_formatter.dart';
|
| +import 'package:dart_style/src/formatter_exception.dart';
|
| +import 'package:dart_style/src/formatter_options.dart';
|
| +import 'package:dart_style/src/io.dart';
|
| +import 'package:dart_style/src/source_code.dart';
|
| +
|
| +void main(List<String> args) {
|
| + var parser = new ArgParser(allowTrailingOptions: true);
|
| +
|
| + parser.addFlag("help",
|
| + abbr: "h", negatable: false, help: "Shows usage information.");
|
| + parser.addOption("line-length",
|
| + abbr: "l", help: "Wrap lines longer than this.", defaultsTo: "80");
|
| + parser.addOption("preserve",
|
| + help: 'Selection to preserve, formatted as "start:length".');
|
| + parser.addFlag("dry-run",
|
| + abbr: "n",
|
| + negatable: false,
|
| + help: "Show which files would be modified but make no changes.");
|
| + parser.addFlag("overwrite",
|
| + abbr: "w",
|
| + negatable: false,
|
| + help: "Overwrite input files with formatted output.");
|
| + parser.addFlag("machine",
|
| + abbr: "m",
|
| + negatable: false,
|
| + help: "Produce machine-readable JSON output.");
|
| + parser.addFlag("follow-links",
|
| + negatable: false,
|
| + help: "Follow links to files and directories.\n"
|
| + "If unset, links will be ignored.");
|
| + parser.addFlag("transform",
|
| + abbr: "t",
|
| + negatable: false,
|
| + help: "Unused flag for compability with the old formatter.");
|
| +
|
| + var argResults;
|
| + try {
|
| + argResults = parser.parse(args);
|
| + } on FormatException catch (err) {
|
| + usageError(parser, err.message);
|
| + }
|
| +
|
| + if (argResults["help"]) {
|
| + printUsage(parser);
|
| + return;
|
| + }
|
| +
|
| + // Can only preserve a selection when parsing from stdin.
|
| + var selection;
|
| +
|
| + if (argResults["preserve"] != null && argResults.rest.isNotEmpty) {
|
| + usageError(parser, "Can only use --preserve when reading from stdin.");
|
| + }
|
| +
|
| + try {
|
| + selection = parseSelection(argResults["preserve"]);
|
| + } on FormatException catch (_) {
|
| + usageError(
|
| + parser,
|
| + '--preserve must be a colon-separated pair of integers, was '
|
| + '"${argResults['preserve']}".');
|
| + }
|
| +
|
| + if (argResults["dry-run"] && argResults["overwrite"]) {
|
| + usageError(
|
| + parser, "Cannot use --dry-run and --overwrite at the same time.");
|
| + }
|
| +
|
| + checkForReporterCollision(String chosen, String other) {
|
| + if (!argResults[other]) return;
|
| +
|
| + usageError(parser, "Cannot use --$chosen and --$other at the same time.");
|
| + }
|
| +
|
| + var reporter = OutputReporter.print;
|
| + if (argResults["dry-run"]) {
|
| + checkForReporterCollision("dry-run", "overwrite");
|
| + checkForReporterCollision("dry-run", "machine");
|
| +
|
| + reporter = OutputReporter.dryRun;
|
| + } else if (argResults["overwrite"]) {
|
| + checkForReporterCollision("overwrite", "machine");
|
| +
|
| + if (argResults.rest.isEmpty) {
|
| + usageError(parser,
|
| + "Cannot use --overwrite without providing any paths to format.");
|
| + }
|
| +
|
| + reporter = OutputReporter.overwrite;
|
| + } else if (argResults["machine"]) {
|
| + reporter = OutputReporter.printJson;
|
| + }
|
| +
|
| + var pageWidth;
|
| +
|
| + try {
|
| + pageWidth = int.parse(argResults["line-length"]);
|
| + } on FormatException catch (_) {
|
| + usageError(
|
| + parser,
|
| + '--line-length must be an integer, was '
|
| + '"${argResults['line-length']}".');
|
| + }
|
| +
|
| + var followLinks = argResults["follow-links"];
|
| +
|
| + var options = new FormatterOptions(reporter,
|
| + pageWidth: pageWidth, followLinks: followLinks);
|
| +
|
| + if (argResults.rest.isEmpty) {
|
| + formatStdin(options, selection);
|
| + } else {
|
| + formatPaths(options, argResults.rest);
|
| + }
|
| +}
|
| +
|
| +List<int> parseSelection(String selection) {
|
| + if (selection == null) return null;
|
| +
|
| + var coordinates = selection.split(":");
|
| + if (coordinates.length != 2) {
|
| + throw new FormatException(
|
| + 'Selection should be a colon-separated pair of integers, "123:45".');
|
| + }
|
| +
|
| + return coordinates.map((coord) => coord.trim()).map(int.parse).toList();
|
| +}
|
| +
|
| +/// Reads input from stdin until it's closed, and the formats it.
|
| +void formatStdin(FormatterOptions options, List<int> selection) {
|
| + var selectionStart = 0;
|
| + var selectionLength = 0;
|
| +
|
| + if (selection != null) {
|
| + selectionStart = selection[0];
|
| + selectionLength = selection[1];
|
| + }
|
| +
|
| + var input = new StringBuffer();
|
| + stdin.transform(new Utf8Decoder()).listen(input.write, onDone: () {
|
| + var formatter = new DartFormatter(pageWidth: options.pageWidth);
|
| + try {
|
| + var source = new SourceCode(input.toString(),
|
| + uri: "stdin",
|
| + selectionStart: selectionStart,
|
| + selectionLength: selectionLength);
|
| + var output = formatter.formatSource(source);
|
| + options.reporter
|
| + .showFile(null, "<stdin>", output, changed: source != output);
|
| + return true;
|
| + } on FormatterException catch (err) {
|
| + stderr.writeln(err.message());
|
| + exitCode = 65; // sysexits.h: EX_DATAERR
|
| + } catch (err, stack) {
|
| + stderr.writeln('''Hit a bug in the formatter when formatting stdin.
|
| +Please report at: github.com/dart-lang/dart_style/issues
|
| +$err
|
| +$stack''');
|
| + exitCode = 70; // sysexits.h: EX_SOFTWARE
|
| + }
|
| + });
|
| +}
|
| +
|
| +/// Formats all of the files and directories given by [paths].
|
| +void formatPaths(FormatterOptions options, List<String> paths) {
|
| + for (var path in paths) {
|
| + var directory = new Directory(path);
|
| + if (directory.existsSync()) {
|
| + if (!processDirectory(options, directory)) {
|
| + exitCode = 65;
|
| + }
|
| + continue;
|
| + }
|
| +
|
| + var file = new File(path);
|
| + if (file.existsSync()) {
|
| + if (!processFile(options, file)) {
|
| + exitCode = 65;
|
| + }
|
| + } else {
|
| + stderr.writeln('No file or directory found at "$path".');
|
| + }
|
| + }
|
| +}
|
| +
|
| +/// Prints [error] and usage help then exits with exit code 64.
|
| +void usageError(ArgParser parser, String error) {
|
| + printUsage(parser, error);
|
| + exit(64);
|
| +}
|
| +
|
| +void printUsage(ArgParser parser, [String error]) {
|
| + var output = stdout;
|
| +
|
| + var message = "Reformats whitespace in Dart source files.";
|
| + if (error != null) {
|
| + message = error;
|
| + output = stdout;
|
| + }
|
| +
|
| + output.write("""$message
|
| +
|
| +Usage: dartfmt [-n|-w] [files or directories...]
|
| +
|
| +${parser.usage}
|
| +""");
|
| +}
|
|
|