package io.airlift.airline;
import com.google.common.base.Preconditions;
import io.airlift.airline.model.ArgumentsMetadata;
import io.airlift.airline.model.CommandMetadata;
import io.airlift.airline.model.OptionMetadata;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static io.airlift.airline.UsageHelper.DEFAULT_OPTION_COMPARATOR;
import static io.airlift.airline.UsageHelper.toSynopsisUsage;
public class CommandUsage
{
private final int columnSize;
private final Comparator<? super OptionMetadata> optionComparator;
public CommandUsage()
{
this(79, DEFAULT_OPTION_COMPARATOR);
}
public CommandUsage(int columnSize)
{
this(columnSize, DEFAULT_OPTION_COMPARATOR);
}
public CommandUsage(int columnSize, @Nullable Comparator<? super OptionMetadata> optionComparator)
{
Preconditions.checkArgument(columnSize > 0, "columnSize must be greater than 0");
this.columnSize = columnSize;
this.optionComparator = optionComparator;
}
/**
* Display the help on System.out.
*/
public void usage(@Nullable String programName, @Nullable String groupName, String commandName, CommandMetadata command)
{
StringBuilder stringBuilder = new StringBuilder();
usage(programName, groupName, commandName, command, stringBuilder);
System.out.println(stringBuilder.toString());
}
/**
* Store the help in the passed string builder.
*/
public void usage(@Nullable String programName, @Nullable String groupName, String commandName, CommandMetadata command, StringBuilder out)
{
usage(programName, groupName, commandName, command, new UsagePrinter(out, columnSize));
}
public void usage(@Nullable String programName, @Nullable String groupName, String commandName, CommandMetadata command, UsagePrinter out)
{
//
// NAME
//
out.append("NAME").newline();
out.newIndentedPrinter(8)
.append(programName)
.append(groupName)
.append(commandName)
.append("-")
.append(command.getDescription())
.newline()
.newline();
//
// SYNOPSIS
//
out.append("SYNOPSIS").newline();
UsagePrinter synopsis = out.newIndentedPrinter(8).newPrinterWithHangingIndent(8);
List<OptionMetadata> options = newArrayList();
if (programName != null) {
synopsis.append(programName).appendWords(toSynopsisUsage(sortOptions(command.getGlobalOptions())));
options.addAll(command.getGlobalOptions());
}
if (groupName != null) {
synopsis.append(groupName).appendWords(toSynopsisUsage(sortOptions(command.getGroupOptions())));
options.addAll(command.getGroupOptions());
}
synopsis.append(commandName).appendWords(toSynopsisUsage(sortOptions(command.getCommandOptions())));
options.addAll(command.getCommandOptions());
// command arguments (optional)
ArgumentsMetadata arguments = command.getArguments();
if (arguments != null) {
synopsis.append("[--]")
.append(UsageHelper.toUsage(arguments));
}
synopsis.newline();
synopsis.newline();
//
// OPTIONS
//
if (options.size() > 0 || arguments != null) {
options = sortOptions(options);
out.append("OPTIONS").newline();
for (OptionMetadata option : options) {
// skip hidden options
if (option.isHidden()) {
continue;
}
// option names
UsagePrinter optionPrinter = out.newIndentedPrinter(8);
optionPrinter.append(UsageHelper.toDescription(option)).newline();
// description
UsagePrinter descriptionPrinter = optionPrinter.newIndentedPrinter(4);
descriptionPrinter.append(option.getDescription()).newline();
descriptionPrinter.newline();
}
if (arguments != null) {
// "--" option
UsagePrinter optionPrinter = out.newIndentedPrinter(8);
optionPrinter.append("--").newline();
// description
UsagePrinter descriptionPrinter = optionPrinter.newIndentedPrinter(4);
descriptionPrinter.append("This option can be used to separate command-line options from the " +
"list of argument, (useful when arguments might be mistaken for command-line options").newline();
descriptionPrinter.newline();
// arguments name
optionPrinter.append(UsageHelper.toDescription(arguments)).newline();
// description
descriptionPrinter.append(arguments.getDescription()).newline();
descriptionPrinter.newline();
}
}
}
private List<OptionMetadata> sortOptions(List<OptionMetadata> options)
{
if (optionComparator != null) {
options = new ArrayList<OptionMetadata>(options);
Collections.sort(options, optionComparator);
}
return options;
}
}