docs: public static void main(String[] args) {
          try {
              if (args.length < 1) {
                  System.err.println();
                  System.err.println(Globals.getWorkbenchInfoString());
                  System.err.println();
                  System.err.println("No task specified.");
              } else {
                  if (isJavaVersionOK() == false || WekaUtils.isWekaVersionOK() == false) {
                      return;
                  }
                  // create standard options
                  FlagOption suppressStatusOutputOption = new FlagOption(
                          "suppressStatusOutput", 'S',
                          "Suppress the task status output that is normally send to stderr.");
                  FlagOption suppressResultOutputOption = new FlagOption(
                          "suppressResultOutput", 'R',
                          "Suppress the task result output that is normally send to stdout.");
                  IntOption statusUpdateFrequencyOption = new IntOption(
                          "statusUpdateFrequency",
                          'F',
                          "How many milliseconds to wait between status updates.",
                          1000, 0, Integer.MAX_VALUE);
                  Option[] extraOptions = new Option[]{
                      suppressStatusOutputOption, suppressResultOutputOption,
                      statusUpdateFrequencyOption};
                  // build a single string by concatenating cli options
                  StringBuilder cliString = new StringBuilder();
                  for (int i = 0; i < args.length; i++) {
                      cliString.append(" ").append(args[i]);
                  }
                  // parse options
                  AbstractTask task;
                  try {
                  	task = (AbstractTask) ClassOption.cliStringToObject(
                  			cliString.toString(), MainTask.class, extraOptions);
                  } catch(Exception e) {
                  	// regular task could not be found, maybe it is a meta task
              		task = (AbstractTask) ClassOption.cliStringToObject(
              				cliString.toString(), MetaMainTask.class, extraOptions);
                  }
                  task.prepareForUse();
                  
                  Object result = null;
                  if (suppressStatusOutputOption.isSet()) {
                      result = task.doTask();
                  } else {
                      System.err.println();
                      System.err.println(Globals.getWorkbenchInfoString());
                      System.err.println();
                      boolean preciseTiming = TimingUtils.enablePreciseTiming();
                      // start the task thread
                      TaskThread taskThread = new TaskThread(task);
                      taskThread.start();
                      int progressAnimIndex = 0;
                      // inform user of progress
                      while (!taskThread.isComplete()) {
                          StringBuilder progressLine = new StringBuilder();
                          progressLine.append(progressAnimSequence[progressAnimIndex]);
                          progressLine.append(' ');
                          progressLine.append(StringUtils.secondsToDHMSString(taskThread.getCPUSecondsElapsed()));
                          progressLine.append(" [");
                          progressLine.append(taskThread.getCurrentStatusString());
                          progressLine.append("] ");
                          double fracComplete = taskThread.getCurrentActivityFracComplete();
                          if (fracComplete >= 0.0) {
                              progressLine.append(StringUtils.doubleToString(
                                      fracComplete * 100.0, 2, 2));
                              progressLine.append("% ");
                          }
                          progressLine.append(taskThread.getCurrentActivityString());
                          while (progressLine.length() < MAX_STATUS_STRING_LENGTH) {
                              progressLine.append(" ");
                          }
                          if (progressLine.length() > MAX_STATUS_STRING_LENGTH) {
                              progressLine.setLength(MAX_STATUS_STRING_LENGTH);
                              progressLine.setCharAt(
                                      MAX_STATUS_STRING_LENGTH - 1, '~');
                          }
                          System.err.print(progressLine.toString());
                          System.err.print('\r');
                          if (++progressAnimIndex >= progressAnimSequence.length) {
                              progressAnimIndex = 0;
                          }
                          try {
                              Thread.sleep(statusUpdateFrequencyOption.getValue());
                          } catch (InterruptedException ignored) {
                              // wake up
                          }
                      }
                      StringBuilder cleanupString = new StringBuilder();
                      for (int i = 0; i < MAX_STATUS_STRING_LENGTH; i++) {
                          cleanupString.append(' ');
                      }
                      System.err.println(cleanupString);
                      result = taskThread.getFinalResult();
                      if (!(result instanceof FailedTaskReport)) {
                          System.err.print("Task completed in "
                                  + StringUtils.secondsToDHMSString(taskThread.getCPUSecondsElapsed()));
                          if (preciseTiming) {
                              System.err.print(" (CPU time)");
                          }
                          System.err.println();
                          System.err.println();
                      }
                  }
                  if (result instanceof FailedTaskReport) {
                      System.err.println("Task failed. Reason: ");
                      ((FailedTaskReport) result).getFailureReason().printStackTrace();
                  } else {
                      if (!suppressResultOutputOption.isSet()) {
                          if (result instanceof Measurement[]) {
                              StringBuilder sb = new StringBuilder();
                              Measurement.getMeasurementsDescription(
                                      (Measurement[]) result, sb, 0);
                              System.out.println(sb.toString());
                          } else {
                              System.out.println(result);
                          }
                          System.out.flush();
                      }
                  }
              }
          } catch (Exception ex) {
              ex.printStackTrace();
          }
      }