de.tototec.cmdoption.DefaultUsageFormatter2 Maven / Gradle / Ivy
package de.tototec.cmdoption;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import de.tototec.cmdoption.internal.FList;
import de.tototec.cmdoption.internal.I18n;
import de.tototec.cmdoption.internal.I18nFactory;
public class DefaultUsageFormatter2 implements UsageFormatter2 {
private final I18n i18n = I18nFactory.getI18n(DefaultUsageFormatter2.class);
private final boolean withCommandDetails;
private int lineLength;
private int colSpace = 2;
private int col1Prefix = 2;
private volatile LineLengthDetector lineLengthDetector;
public DefaultUsageFormatter2(final boolean withCommandDetails, final int lineLength,
final LineLengthDetector lineLengthDetector) {
this.withCommandDetails = withCommandDetails;
this.lineLengthDetector = lineLengthDetector;
this.lineLength = lineLength;
}
public DefaultUsageFormatter2(final boolean withCommandDetails, final int lineLength) {
this(withCommandDetails, lineLength, null);
}
public DefaultUsageFormatter2(final boolean withCommandDetails) {
this(withCommandDetails, 80, null);
}
protected int getLineLength() {
if (lineLengthDetector != null) {
synchronized (this) {
if (lineLengthDetector != null) {
final Integer detectedLength = lineLengthDetector.detectOrNull();
if (detectedLength != null) {
lineLength = detectedLength.intValue();
}
// do it only once
lineLengthDetector = null;
}
}
}
return lineLength;
}
protected String translate(final ResourceBundle resourceBundle, final String string) {
if (resourceBundle != null) {
try {
return resourceBundle.getString(string);
} catch (final MissingResourceException e) {
// no translation available
}
}
return string;
}
protected String[] translate(final ResourceBundle resourceBundle, final String[] strings) {
final String[] translated = new String[strings.length];
for (int i = 0; i < strings.length; ++i) {
translated[i] = translate(resourceBundle, strings[i]);
}
return translated;
}
public void format(final PrintStream output, final CmdlineModel cmdlineModel) {
final ArrayList sortedOptions = new ArrayList(cmdlineModel.getOptions());
for (final Iterator it = sortedOptions.iterator(); it.hasNext();) {
if (it.next().isHidden()) {
it.remove();
}
}
Collections.sort(sortedOptions, new OptionHandle.OptionHandleComparator());
final ArrayList sortedCommands = new ArrayList(cmdlineModel.getCommands());
for (final Iterator it = sortedCommands.iterator(); it.hasNext();) {
if (it.next().isHidden()) {
it.remove();
}
}
Collections.sort(sortedCommands, new CommandHandle.CommandHandleComparator());
// About
if (cmdlineModel.getAboutLine() != null && cmdlineModel.getAboutLine().length() > 0) {
output.append(translate(cmdlineModel.getResourceBundle(), cmdlineModel.getAboutLine())).append("\n\n");
}
// Usage
output.append(i18n.tr("Usage:")).append(" ");
output.append(cmdlineModel.getProgramName() == null ? i18n.tr("program") : cmdlineModel.getProgramName());
if (!sortedOptions.isEmpty()) {
output.append(" ").append(i18n.tr("[options]"));
}
if (cmdlineModel.getParameter() != null) {
output.append(" ").append(i18n.tr("[parameter]"));
}
if (!sortedCommands.isEmpty()) {
output.append(" ").append(i18n.tr("[command]"));
boolean cmdsHaveOptions = false;
boolean cmdsHaveParameter = false;
for (final CommandHandle cmd : sortedCommands) {
cmdsHaveOptions |= !cmd.getCmdlineParser().getCmdlineModel().getOptions().isEmpty();
cmdsHaveParameter |= cmd.getCmdlineParser().getCmdlineModel().getParameter() != null;
}
if (cmdsHaveOptions) {
output.append(" ").append(i18n.tr("[command options]"));
}
if (cmdsHaveParameter) {
output.append(" ").append(i18n.tr("[command parameters]"));
}
}
output.append("\n");
formatOptions(output, sortedOptions, "\n" + i18n.tr("Options:"), cmdlineModel.getResourceBundle());
formatCommands(output, sortedCommands, "\n" + i18n.tr("Commands:"), cmdlineModel.getResourceBundle());
if (withCommandDetails) {
for (final CommandHandle command : sortedCommands) {
final ArrayList commandOptions = new ArrayList(command.getCmdlineParser()
.getCmdlineModel().getOptions());
for (final Iterator it = commandOptions.iterator(); it.hasNext();) {
if (it.next().isHidden()) {
it.remove();
}
}
Collections.sort(commandOptions, new OptionHandle.OptionHandleComparator());
formatOptions(
output,
commandOptions,
"\n" + i18n.tr("Options for command:") + " "
+ FList.mkString(command.getNames(), ", "),
cmdlineModel.getResourceBundle());
formatParameter(
output,
command.getCmdlineParser().getCmdlineModel().getParameter(),
"\n" + i18n.tr("Parameter for command:") + " "
+ FList.mkString(command.getNames(), ", "),
cmdlineModel.getResourceBundle());
}
}
// Parameter
formatParameter(output, cmdlineModel.getParameter(), "\n" + i18n.tr("Parameter:"),
cmdlineModel.getResourceBundle());
}
protected void formatParameter(final PrintStream output, final OptionHandle parameter, final String title,
final ResourceBundle resourceBundle) {
if (parameter == null) {
return;
}
output.append(title).append("\n");
mkSpace(output, col1Prefix);
final String[] translatedArgs = translate(resourceBundle, parameter.getArgs());
output.append(FList.mkString(translatedArgs, " "));
if (parameter.getDescription() != null) {
mkSpace(output, colSpace);
output.append(MessageFormat.format(translate(resourceBundle, parameter.getDescription()),
(Object[]) translatedArgs));
}
output.append("\n");
}
protected void formatOptions(final PrintStream output, final List options, final String title,
final ResourceBundle resourceBundle) {
if (options == null || options.isEmpty()) {
return;
}
final LinkedList optionsToFormat = new LinkedList();
boolean hasOptions = false;
for (final OptionHandle option : options) {
if (option.isHidden()) {
continue;
}
hasOptions = true;
final String optionNames = FList.mkString(option.getNames(), ",");
final String[] translatedArgs = translate(resourceBundle, option.getArgs());
final String argNames = FList.mkString(translatedArgs, " ");
optionsToFormat
.add(new String[] {
optionNames + (argNames.length() == 0 ? "" : (" " + argNames)),
MessageFormat.format(translate(resourceBundle, option.getDescription()),
(Object[]) translatedArgs) });
}
if (!hasOptions) {
return;
}
if (title != null) {
output.append(title).append("\n");
}
formatTable(output, optionsToFormat, col1Prefix, colSpace, getLineLength());
}
protected void formatCommands(final PrintStream output, final List commands, final String title,
final ResourceBundle resourceBundle) {
if (commands == null || commands.isEmpty()) {
return;
}
if (title != null) {
output.append(title).append("\n");
}
final LinkedList commandsToFormat = new LinkedList();
for (final CommandHandle option : commands) {
final String commandNames = FList.mkString(option.getNames(), ",");
commandsToFormat.add(new String[] { commandNames, translate(resourceBundle, option.getDescription()) });
}
formatTable(output, commandsToFormat, col1Prefix, colSpace, getLineLength());
}
public static void mkSpace(final PrintStream output, final int space) {
for (int i = 0; i < space; ++i) {
output.append(" ");
}
}
public static void formatTable(final PrintStream output, final List twoColData, final int prefix,
final int space, final int maxLineLength) {
// Calc first col width
int firstColSize = 2;
for (final String[] col : twoColData) {
if (col.length > 0 && col[0] != null) {
firstColSize = Math.max(firstColSize, col[0].length());
}
}
final boolean secondColInNewLine = ((prefix + space + firstColSize + 10) > maxLineLength);
// Write output
for (final String[] col : twoColData) {
if (col.length > 0) {
// first col
mkSpace(output, prefix);
int cursor = prefix;
if (col[0] != null) {
output.append(col[0]);
cursor += col[0].length();
}
// fill space to next col
if (secondColInNewLine) {
output.append("\n");
} else {
mkSpace(output, prefix + firstColSize + space - cursor);
}
// second col
if (col[1] != null) {
if (secondColInNewLine) {
wrap(output, col[1], prefix + space, maxLineLength - prefix - space);
} else {
wrap(output, col[1], prefix + space + firstColSize, maxLineLength - prefix - space
- firstColSize);
}
}
}
output.append("\n");
}
}
public static void wrap(final PrintStream output, String text, final int nextLinePrefix, final int lineLength) {
final int _lineLength = Math.max(lineLength, 0);
text = text.trim();
if (text.length() <= _lineLength) {
output.append(text);
} else {
int bestWrap = -1;
if (" ".equals(text.substring(_lineLength, _lineLength + 1))) {
bestWrap = _lineLength;
} else {
bestWrap = text.substring(0, _lineLength).lastIndexOf(" ");
}
if (bestWrap == -1) {
bestWrap = text.indexOf(" ");
}
if (bestWrap > 0) {
output.append(text.substring(0, bestWrap)).append("\n");
for (int i = 0; i < nextLinePrefix; ++i) {
output.append(" ");
}
wrap(output, text.substring(bestWrap), nextLinePrefix, _lineLength);
} else {
output.append(text);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy