Add configuration option for output format (#1996)

Adds a configuartion option to specify the output format for generated
docs, defaulting to 'html'. Hidden from help usage for the time being.
diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart
index 8b49977..822be91 100644
--- a/lib/dartdoc.dart
+++ b/lib/dartdoc.dart
@@ -13,6 +13,7 @@
 import 'dart:io';
 
 import 'package:dartdoc/src/dartdoc_options.dart';
+import 'package:dartdoc/src/empty_generator.dart';
 import 'package:dartdoc/src/generator.dart';
 import 'package:dartdoc/src/html/html_generator.dart';
 import 'package:dartdoc/src/logging.dart';
@@ -68,9 +69,9 @@
     return new Dartdoc._(config, generators);
   }
 
-  /// An asynchronous factory method that builds
+  /// An asynchronous factory method that builds an EmptyGenerator.
   static Future<Dartdoc> withEmptyGenerator(DartdocOptionContext config) async {
-    List<Generator> generators = await initEmptyGenerators(config);
+    List<Generator> generators = [await createEmptyGenerator(config)];
     return new Dartdoc._(config, generators);
   }
 
diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart
index 23ed768..45cdf2d 100644
--- a/lib/src/dartdoc_options.dart
+++ b/lib/src/dartdoc_options.dart
@@ -1422,6 +1422,8 @@
 
   bool isPackageExcluded(String name) =>
       excludePackages.any((pattern) => name == pattern);
+
+  String get format => optionSet['format'].valueAt(context);
 }
 
 /// Instantiate dartdoc's configuration file and options parser with the
@@ -1624,6 +1626,8 @@
             'exist. Executables for different platforms are specified by '
             'giving the platform name as a key, and a list of strings as the '
             'command.'),
+    // TODO(jdkoren): unhide when this feature is in working order.
+    new DartdocOptionArgOnly<String>('format', 'html', hide: true)
     // TODO(jcollins-g): refactor so there is a single static "create" for
     // each DartdocOptionContext that traverses the inheritance tree itself.
   ]
diff --git a/lib/src/empty_generator.dart b/lib/src/empty_generator.dart
index 476dd67..12e8d34 100644
--- a/lib/src/empty_generator.dart
+++ b/lib/src/empty_generator.dart
@@ -2,6 +2,7 @@
 
 import 'dart:async';
 
+import 'package:dartdoc/dartdoc.dart';
 import 'package:dartdoc/src/generator.dart';
 import 'package:dartdoc/src/model.dart';
 import 'package:dartdoc/src/model_utils.dart';
@@ -39,3 +40,7 @@
   @override
   Set<String> get writtenFiles => new Set();
 }
+
+Future<Generator> createEmptyGenerator(DartdocOptionContext config) async {
+  return EmptyGenerator();
+}
diff --git a/lib/src/generator.dart b/lib/src/generator.dart
index bd35988..217e95a 100644
--- a/lib/src/generator.dart
+++ b/lib/src/generator.dart
@@ -7,7 +7,10 @@
 
 import 'dart:async' show Stream, Future;
 
+import 'package:dartdoc/dartdoc.dart';
+import 'package:dartdoc/src/empty_generator.dart';
 import 'package:dartdoc/src/model.dart' show PackageGraph;
+import 'package:dartdoc/src/html/html_generator.dart';
 
 /// An abstract class that defines a generator that generates documentation for
 /// a given package.
@@ -24,3 +27,17 @@
   /// Fetches all filenames written by this generator.
   Set<String> get writtenFiles;
 }
+
+/// Initialize and setup the generators.
+Future<List<Generator>> initGenerators(GeneratorContext config) async {
+  // TODO(jdkoren) this could support multiple generators.
+  var format = config.format;
+  switch (format) {
+    case 'html':
+      return [await createHtmlGenerator(config)];
+    case 'md':
+      return [await createEmptyGenerator(config)];
+    default:
+      throw DartdocFailure('Unsupported output format: ${format}');
+  }
+}
diff --git a/lib/src/html/html_generator.dart b/lib/src/html/html_generator.dart
index 89b6402..af2c8ee 100644
--- a/lib/src/html/html_generator.dart
+++ b/lib/src/html/html_generator.dart
@@ -9,7 +9,6 @@
 import 'dart:isolate';
 
 import 'package:dartdoc/dartdoc.dart';
-import 'package:dartdoc/src/empty_generator.dart';
 import 'package:dartdoc/src/generator.dart';
 import 'package:dartdoc/src/html/html_generator_instance.dart';
 import 'package:dartdoc/src/html/template_data.dart';
@@ -132,12 +131,8 @@
       : this.toolVersion = toolVersion ?? 'unknown';
 }
 
-Future<List<Generator>> initEmptyGenerators(DartdocOptionContext config) async {
-  return [EmptyGenerator()];
-}
-
 /// Initialize and setup the generators.
-Future<List<Generator>> initGenerators(GeneratorContext config) async {
+Future<HtmlGenerator> createHtmlGenerator(GeneratorContext config) async {
   // TODO(jcollins-g): Rationalize based on GeneratorContext all the way down
   // through the generators.
   HtmlGeneratorOptions options = new HtmlGeneratorOptions(
@@ -147,14 +142,12 @@
       faviconPath: config.favicon,
       prettyIndexJson: config.prettyIndexJson);
 
-  return [
-    await HtmlGenerator.create(
-      options: options,
-      headers: config.header,
-      footers: config.footer,
-      footerTexts: config.footerTextPaths,
-    )
-  ];
+  return await HtmlGenerator.create(
+    options: options,
+    headers: config.header,
+    footers: config.footer,
+    footerTexts: config.footerTextPaths,
+  );
 }
 
 Uri _sdkFooterCopyrightUri;
diff --git a/test/dartdoc_test.dart b/test/dartdoc_test.dart
index 29779a0..426de97 100644
--- a/test/dartdoc_test.dart
+++ b/test/dartdoc_test.dart
@@ -364,5 +364,14 @@
           dart_bear.allClasses.map((cls) => cls.name).contains('Bear'), isTrue);
       expect(p.packageMap["Dart"].publicLibraries, hasLength(3));
     });
+
+    test('generate docs with unsupported format fails', () async {
+      try {
+        await buildDartdoc(['--format', 'bad'], testPackageOptions, tempDir);
+        fail('dartdoc should fail on unsupported format');
+      } catch (e) {
+        expect(e is DartdocFailure, isTrue);
+      }
+    });
   }, timeout: new Timeout.factor(8));
 }