The help command can now output html for the command-line reference page.

An upcoming change will pipe this to an actual page.

--
MOS_MIGRATED_REVID=125545220
diff --git a/src/main/java/com/google/devtools/common/options/OptionsParser.java b/src/main/java/com/google/devtools/common/options/OptionsParser.java
index 83a7b08..301f2d4 100644
--- a/src/main/java/com/google/devtools/common/options/OptionsParser.java
+++ b/src/main/java/com/google/devtools/common/options/OptionsParser.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.escape.Escaper;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -436,7 +437,6 @@
                                 HelpVerbosity helpVerbosity) {
     StringBuilder desc = new StringBuilder();
     if (!impl.getOptionsClasses().isEmpty()) {
-
       List<Field> allFields = Lists.newArrayList();
       for (Class<? extends OptionsBase> optionsClass : impl.getOptionsClasses()) {
         allFields.addAll(impl.getAnnotatedFieldsFor(optionsClass));
@@ -466,6 +466,52 @@
   }
 
   /**
+   * Returns a description of all the options this parser can digest.
+   * In addition to {@link Option} annotations, this method also
+   * interprets {@link OptionsUsage} annotations which give an intuitive short
+   * description for the options.
+   *
+   * @param categoryDescriptions a mapping from category names to category
+   *   descriptions.  Options of the same category (see {@link
+   *   Option#category}) will be grouped together, preceded by the description
+   *   of the category.
+   */
+  public String describeOptionsHtml(Map<String, String> categoryDescriptions, Escaper escaper) {
+    StringBuilder desc = new StringBuilder();
+    if (!impl.getOptionsClasses().isEmpty()) {
+      List<Field> allFields = Lists.newArrayList();
+      for (Class<? extends OptionsBase> optionsClass : impl.getOptionsClasses()) {
+        allFields.addAll(impl.getAnnotatedFieldsFor(optionsClass));
+      }
+      Collections.sort(allFields, OptionsUsage.BY_CATEGORY);
+      String prevCategory = null;
+
+      for (Field optionField : allFields) {
+        String category = optionField.getAnnotation(Option.class).category();
+        DocumentationLevel level = documentationLevel(category);
+        if (!category.equals(prevCategory) && level == DocumentationLevel.DOCUMENTED) {
+          String description = categoryDescriptions.get(category);
+          if (description == null) {
+            description = "Options category '" + category + "'";
+          }
+          if (prevCategory != null) {
+            desc.append("</dl>\n\n");
+          }
+          desc.append(escaper.escape(description)).append(":\n");
+          desc.append("<dl>");
+          prevCategory = category;
+        }
+
+        if (level == DocumentationLevel.DOCUMENTED) {
+          OptionsUsage.getUsageHtml(optionField, desc, escaper);
+        }
+      }
+      desc.append("</dl>\n");
+    }
+    return desc.toString();
+  }
+
+  /**
    * Returns a string listing the possible flag completion for this command along with the command
    * completion if any. See {@link OptionsUsage#getCompletion(Field, StringBuilder)} for more
    * details on the format for the flag completion.