SLIDER-458. Slider CLI help is very verbose
diff --git a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
index 66797ae..65eaaff 100644
--- a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
+++ b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
@@ -375,7 +375,7 @@
       exitCode = actionThaw(clusterName, serviceArgs.getActionThawArgs());
     } else if (ACTION_DESTROY.equals(action)) {
       exitCode = actionDestroy(clusterName);
-    } else if (ACTION_DIAGNOSTIC.equals(action)) {
+    } else if (ACTION_DIAGNOSTICS.equals(action)) {
       exitCode = actionDiagnostic(serviceArgs.getActionDiagnosticArgs());
     } else if (ACTION_EXISTS.equals(action)) {
       exitCode = actionExists(clusterName,
@@ -675,8 +675,10 @@
       throws YarnException, IOException {
 
     Path srcFile = null;
-    if (StringUtils.isEmpty(installKeytabInfo.folder )) {
-      throw new BadCommandArgumentsException("A valid destination keytab sub-folder name is required (e.g. 'security').");
+    if (StringUtils.isEmpty(installKeytabInfo.folder)) {
+      throw new BadCommandArgumentsException(
+          "A valid destination keytab sub-folder name is required (e.g. 'security').\n"
+              + CommonArgs.usage(serviceArgs, ACTION_INSTALL_KEYTAB));
     }
 
     if (StringUtils.isEmpty(installKeytabInfo.keytabUri)) {
@@ -717,8 +719,10 @@
       IOException {
 
     Path srcFile = null;
-    if (StringUtils.isEmpty(installPkgInfo.name )) {
-      throw new BadCommandArgumentsException("A valid application type name is required (e.g. HBASE).");
+    if (StringUtils.isEmpty(installPkgInfo.name)) {
+      throw new BadCommandArgumentsException(
+          "A valid application type name is required (e.g. HBASE).\n"
+              + CommonArgs.usage(serviceArgs, ACTION_INSTALL_PACKAGE));
     }
 
     if (StringUtils.isEmpty(installPkgInfo.packageURI)) {
@@ -2568,7 +2572,7 @@
         outputExport(publishedExports, registryArgs);
       } else {
         // it's an unknown command
-        log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTIC));
+        log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTICS));
         return EXIT_USAGE;
       }
 //      JDK7
@@ -2648,7 +2652,7 @@
         actionDiagnosticIntelligent(diagnosticArgs);
       } else {
         // it's an unknown option
-        log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTIC));
+        log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTICS));
         return EXIT_USAGE;
       }
     } catch (Exception e) {
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java
index f48f902..d54aa8e 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java
@@ -4,7 +4,7 @@
 import com.beust.jcommander.Parameters;
 
 @Parameters(
-  commandNames = {SliderActions.ACTION_DIAGNOSTIC, SliderActions.ACTION_DIAGNOSTICS},
+  commandNames = {SliderActions.ACTION_DIAGNOSTICS},
   commandDescription = SliderActions.DESCRIBE_ACTION_DIAGNOSTIC)
 public class ActionDiagnosticArgs extends AbstractActionArgs {
 
@@ -42,7 +42,7 @@
 	  public String all;
 	
 	  @Parameter(names = {ARG_LEVEL}, 
-	      description = "diagnoze the application intelligently")
+	      description = "diagnose each slider configuration one by one")
 	  public String level;
 
 	  /**
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java
index cf8cc2f..5a1c049 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java
@@ -218,7 +218,7 @@
     } else if (SliderActions.ACTION_DESTROY.equals(action)) {
       bindCoreAction(actionDestroyArgs);
 
-    } else if (SliderActions.ACTION_DIAGNOSTIC.equals(action)) {
+    } else if (SliderActions.ACTION_DIAGNOSTICS.equals(action)) {
       bindCoreAction(actionDiagnosticArgs);
 
     } else if (SliderActions.ACTION_EXISTS.equals(action)) {
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java
index 5113617..57d5fb4 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java
@@ -20,6 +20,7 @@
 
 import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
+import com.beust.jcommander.ParameterDescription;
 import com.beust.jcommander.ParameterException;
 
 import org.apache.hadoop.conf.Configuration;
@@ -50,7 +51,7 @@
   protected static final Logger log = LoggerFactory.getLogger(CommonArgs.class);
 
 
-  private static final int DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME = 20;
+  private static final int DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME = 30;
 
 
   @Parameter(names = ARG_HELP, help = true)
@@ -111,28 +112,32 @@
     if (commandOfInterest == null) {
       // JCommander.usage is too verbose for a command with many options like
       // slider no short version of that is found Instead, we compose our msg by
-      helperMessage.append("\n");
-      helperMessage.append("Usage: slider COMMAND [options]\n");
+      helperMessage.append("\nUsage: slider COMMAND [options]\n");
       helperMessage.append("where COMMAND is one of\n");
       for (String jcommand : serviceArgs.commander.getCommands().keySet()) {
         helperMessage.append(String.format("\t%-"
-            + DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME + "s-%s", jcommand,
+            + DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME + "s%s", jcommand,
             serviceArgs.commander.getCommandDescription(jcommand) + "\n"));
       }
       helperMessage
           .append("Most commands print help when invoked without parameters");
       result = helperMessage.toString();
     } else {
-      // Jcommander framework doesn't provide a working API to fetch all options
-      // we have to compose options' helper message per action our own
-      serviceArgs.commander.usage(commandOfInterest, helperMessage);
-      // eliminate all linebreaks/tabs as there are too many
-      result = helperMessage.toString().replaceAll("\n|\t|\\s{3,}", " ");
-      // insert linebreak and indents
-      result = result.replaceAll("(--|-D|-S)", "\n\t$1");
-      // put options and their abbreviations on the same line
-      result = result.replaceAll(",\\s*\n\t--", ", --");
-      result = result.replaceAll("Usage:", "\nUsage:");
+      helperMessage.append("\nUsage: slider " + commandOfInterest);
+      helperMessage.append(serviceArgs.coreAction.getMinParams() > 0 ? " <application>" : "");
+      helperMessage.append("\n");
+      for (ParameterDescription paramDesc : serviceArgs.commander.getCommands()
+          .get(commandOfInterest).getParameters()) {
+        String optional = paramDesc.getParameter().required() ? "  (required)"
+            : "  (optional)";
+        String paramName = paramDesc.getParameterized().getType() == Boolean.TYPE ? paramDesc
+            .getLongestName() : paramDesc.getLongestName() + " <"
+            + paramDesc.getParameterized().getName() + ">";
+        helperMessage.append(String.format("\t%-"
+            + DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME + "s%s", paramName,
+            paramDesc.getDescription() + optional + "\n"));
+        result = helperMessage.toString();
+      }
     }
     return result;
   }
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java b/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java
index 1383bc7..87e4582 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java
@@ -43,7 +43,6 @@
   String ACTION_STATUS = "status";
   String ACTION_THAW = "start";
   String ACTION_VERSION = "version";
-  String ACTION_DIAGNOSTIC = "diagnostic";
   String ACTION_DIAGNOSTICS = "diagnostics";
   String ACTION_INSTALL_PACKAGE = "install-package";
   String ACTION_INSTALL_KEYTAB = "install-keytab";
diff --git a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy
index 3f7c50f..8aacf6a 100644
--- a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy
@@ -58,7 +58,7 @@
   public void testActionWithoutOptions() throws Throwable {
     launchExpectingException(SliderClient,
                              new Configuration(),
-                             "Usage: build [options] Options:",
+                             "Usage: slider build <application>",
                              [SliderActions.ACTION_BUILD])
   }
 
diff --git a/slider-core/src/test/groovy/org/apache/slider/client/TestDiagnostics.groovy b/slider-core/src/test/groovy/org/apache/slider/client/TestDiagnostics.groovy
index 57126f8..04f019f 100644
--- a/slider-core/src/test/groovy/org/apache/slider/client/TestDiagnostics.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/client/TestDiagnostics.groovy
@@ -42,7 +42,7 @@
         //config includes RM binding info
         new YarnConfiguration(miniCluster.config),
         //varargs list of command line params
-        [SliderActions.ACTION_DIAGNOSTIC,
+        [SliderActions.ACTION_DIAGNOSTICS,
          Arguments.ARG_CLIENT]
     )
     def client = launcher.service