protected void printUsageDelegate(
      CommandSession session,
      Object action,
      Map<Option, Field> optionsMap,
      Map<Argument, Field> argsMap,
      PrintStream out) {
    Command command = action.getClass().getAnnotation(Command.class);
    Terminal term = session != null ? (Terminal) session.get(".jline.terminal") : null;
    List<Argument> arguments = new ArrayList<Argument>(argsMap.keySet());
    Collections.sort(
        arguments,
        new Comparator<Argument>() {
          public int compare(Argument o1, Argument o2) {
            return Integer.valueOf(o1.index()).compareTo(Integer.valueOf(o2.index()));
          }
        });

    String commandName = command != null ? command.name() : name;
    String commandScope = command != null ? command.scope() : scope;
    String commandDescription =
        command != null ? command.description() : "No description available for " + name + ".";
    String commandDetailedDescription = command != null ? command.detailedDescription() : "";

    Set<Option> options = new TreeSet<Option>(CommandArguments.OPTION_COMPARATOR);
    options.addAll(optionsMap.keySet());
    options.add(HELP);
    boolean globalScope = NameScoping.isGlobalScope(session, scope);
    out.println(
        Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("DESCRIPTION").a(Ansi.Attribute.RESET));
    out.print("        ");
    if (commandName != null) {
      if (globalScope) {
        out.println(
            Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(commandName).a(Ansi.Attribute.RESET));
      } else {
        out.println(
            Ansi.ansi()
                .a(commandScope)
                .a(":")
                .a(Ansi.Attribute.INTENSITY_BOLD)
                .a(commandName)
                .a(Ansi.Attribute.RESET));
      }
      out.println();
    }
    String description = commandDescription;
    if (isBlank(description)) {
      description = "No description available for " + name + ".";
    }
    out.print("\t");
    out.println(description);
    out.println();
    out.println("\tLoaded from");
    out.println("\t" + scriptFile);
    out.println();

    StringBuffer syntax = new StringBuffer();
    if (globalScope) {
      syntax.append(commandName);
    } else {
      syntax.append(String.format("%s:%s", commandScope, commandName));
    }

    if (options.size() > 0) {
      syntax.append(" [options]");
    }
    if (arguments.size() > 0) {
      syntax.append(' ');
      for (Argument argument : arguments) {
        if (!argument.required()) {
          syntax.append(String.format("[%s] ", argument.name()));
        } else {
          syntax.append(String.format("%s ", argument.name()));
        }
      }
    }

    out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("SYNTAX").a(Ansi.Attribute.RESET));
    out.print("        ");
    out.println(syntax.toString());
    out.println();
    if (arguments.size() > 0) {
      out.println(
          Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("ARGUMENTS").a(Ansi.Attribute.RESET));
      for (Argument argument : arguments) {
        out.print("        ");
        out.println(
            Ansi.ansi()
                .a(Ansi.Attribute.INTENSITY_BOLD)
                .a(argument.name())
                .a(Ansi.Attribute.RESET));
        printFormatted(
            "                ", argument.description(), term != null ? term.getWidth() : 80, out);
        if (!argument.required()) {
          if (argument.valueToShowInHelp() != null && argument.valueToShowInHelp().length() != 0) {
            try {
              if (Argument.DEFAULT_STRING.equals(argument.valueToShowInHelp())) {
                argsMap.get(argument).setAccessible(true);
                Object o = argsMap.get(argument).get(action);
                printObjectDefaultsTo(out, o);
              } else {
                printDefaultsTo(out, argument.valueToShowInHelp());
              }
            } catch (Throwable t) {
              // Ignore
            }
          }
        }
      }
      out.println();
    }
    if (options.size() > 0) {
      out.println(
          Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("OPTIONS").a(Ansi.Attribute.RESET));
      for (Option option : options) {
        String opt = option.name();
        for (String alias : option.aliases()) {
          opt += ", " + alias;
        }
        out.print("        ");
        out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(opt).a(Ansi.Attribute.RESET));
        printFormatted(
            "                ", option.description(), term != null ? term.getWidth() : 80, out);
        if (option.valueToShowInHelp() != null && option.valueToShowInHelp().length() != 0) {
          try {
            if (Option.DEFAULT_STRING.equals(option.valueToShowInHelp())) {
              optionsMap.get(option).setAccessible(true);
              Object o = optionsMap.get(option).get(action);
              printObjectDefaultsTo(out, o);
            } else {
              printDefaultsTo(out, option.valueToShowInHelp());
            }
          } catch (Throwable t) {
            // Ignore
          }
        }
      }
      out.println();
    }
    if (commandDetailedDescription.length() > 0) {
      out.println(
          Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("DETAILS").a(Ansi.Attribute.RESET));
      String desc = loadDescription(action.getClass(), commandDetailedDescription);
      printFormattedFixed("        ", desc, term != null ? term.getWidth() : 80, out);
    }
  }