Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cli] Full config help details #4928

Merged
merged 2 commits into from
Jan 7, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,21 @@
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Locale;
import java.util.Map;

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
import static org.apache.commons.lang3.StringUtils.isEmpty;

@SuppressWarnings("unused")
@Command(name = "config-help", description = "Config help for chosen lang")
public class ConfigHelp implements Runnable {

private static final Logger LOGGER = LoggerFactory.getLogger(Generate.class);

public static final String FORMAT_TEXT = "text";
public static final String FORMAT_MARKDOWN = "markdown";
public static final String FORMAT_YAMLSAMPLE = "yamlsample";
private static final String FORMAT_TEXT = "text";
private static final String FORMAT_MARKDOWN = "markdown";
private static final String FORMAT_YAMLSAMPLE = "yamlsample";

@Option(name = {"-g",
"--generator-name"}, title = "generator name", description = "generator to get config help for")
Expand All @@ -61,18 +63,41 @@ public class ConfigHelp implements Runnable {
FORMAT_TEXT, FORMAT_MARKDOWN, FORMAT_YAMLSAMPLE})
private String format;

@Option(name = {"--import-mappings"}, title = "import mappings", description = "displays the default import mappings (types and aliases, and what imports they will pull into the template)")
private Boolean importMappings;

@Option(name = {"--language-specific-primitive"}, title = "language specific primitives", description = "displays the language specific primitives (types which require no additional imports, or which may conflict with user defined model names)")
private Boolean languageSpecificPrimitives;

@Option(name = {"--reserved-words"}, title = "language specific reserved words", description = "displays the reserved words which may result in renamed model or property names")
private Boolean reservedWords;

@Option(name = {"--instantiation-types"}, title = "instantiation types", description = "displays types used to instantiate simple type/alias names")
private Boolean instantiationTypes;

@Option(name = {
"--markdown-header"}, title = "markdown header", description = "When format=markdown, include this option to write out markdown headers (e.g. for docusaurus).")
private Boolean markdownHeader;

@Option(name = {"--full-details"}, title = "full generator details", description = "displays CLI options as well as other configs/mappings (implies --instantiation-types, --reserved-words, --language-specific-primitives, --import-mappings, --supporting-files)")
private Boolean fullDetails;

private String newline = System.lineSeparator();

@Override public void run() {
@Override
public void run() {
if (isEmpty(generatorName)) {
LOGGER.error("[error] A generator name (--generator-name / -g) is required.");
System.exit(1);
}

if (Boolean.TRUE.equals(fullDetails)) {
instantiationTypes = Boolean.TRUE;
reservedWords = Boolean.TRUE;
languageSpecificPrimitives = Boolean.TRUE;
importMappings = Boolean.TRUE;
}

try {
StringBuilder sb = new StringBuilder();
CodegenConfig config = CodegenConfigLoader.forName(generatorName);
Expand All @@ -97,9 +122,9 @@ public class ConfigHelp implements Runnable {

if (!isEmpty(outputFile)) {
File out = Paths.get(outputFile).toFile();
//noinspection ResultOfMethodCallIgnored
File parentFolder = out.getParentFile();
if (parentFolder != null && parentFolder.isDirectory()) {
//noinspection ResultOfMethodCallIgnored
parentFolder.mkdirs();
}

Expand All @@ -119,34 +144,6 @@ public class ConfigHelp implements Runnable {
}
}

private void generateYamlSample(StringBuilder sb, CodegenConfig config) {

for (CliOption langCliOption : config.cliOptions()) {

sb.append("# Description: ").append(langCliOption.getDescription()).append(newline);

Map<String, String> enums = langCliOption.getEnum();
if (enums != null) {
sb.append("# Available Values:").append(newline);

for (Map.Entry<String, String> entry : enums.entrySet()) {
sb.append("# ").append(entry.getKey()).append(newline);
sb.append("# ").append(entry.getValue()).append(newline);
}
}

String defaultValue = langCliOption.getDefault();

if (defaultValue != null) {
sb.append(langCliOption.getOpt()).append(": ").append(defaultValue).append(newline);
} else {
sb.append("# ").append(langCliOption.getOpt()).append(": ").append(newline);
}

sb.append(newline);
}
}

private void generateMarkdownHelp(StringBuilder sb, CodegenConfig config) {
if (Boolean.TRUE.equals(markdownHeader)) {
sb.append("---").append(newline);
Expand Down Expand Up @@ -197,6 +194,91 @@ private void generateMarkdownHelp(StringBuilder sb, CodegenConfig config) {

sb.append(newline);
}


if (Boolean.TRUE.equals(importMappings)) {
sb.append(newline);
sb.append("## IMPORT MAPPING");
sb.append(newline);
sb.append(newline);

sb.append("| Type/Alias | Imports |").append(newline);
sb.append("| ---------- | ------- |").append(newline);

config.importMapping().forEach((key, value)-> {
sb.append("|").append(escapeHtml4(key)).append("|").append(escapeHtml4(value)).append("|");
sb.append(newline);
});

sb.append(newline);
}

if (Boolean.TRUE.equals(instantiationTypes)) {
sb.append(newline);
sb.append("## INSTANTIATION TYPES");
sb.append(newline);
sb.append(newline);

sb.append("| Type/Alias | Instantiated By |").append(newline);
sb.append("| ---------- | --------------- |").append(newline);

config.instantiationTypes().forEach((key, value)-> {
sb.append("|").append(escapeHtml4(key)).append("|").append(escapeHtml4(value)).append("|");
sb.append(newline);
});

sb.append(newline);
}

if (Boolean.TRUE.equals(languageSpecificPrimitives)) {
sb.append(newline);
sb.append("## LANGUAGE PRIMITIVES");
sb.append(newline);
sb.append(newline);
sb.append("<ul data-columns=\"2\" style=\"list-style-type: disc;-webkit-columns:2;-moz-columns:2;columns:2;-moz-column-fill:auto;column-fill:auto\">");
config.languageSpecificPrimitives().forEach(s -> sb.append("<li>").append(escapeHtml4(s)).append("</li>").append(newline));
sb.append("</ul>");
sb.append(newline);
}

if (Boolean.TRUE.equals(reservedWords)) {
sb.append(newline);
sb.append("## RESERVED WORDS");
sb.append(newline);
sb.append(newline);
sb.append("<ul data-columns=\"2\" style=\"list-style-type: disc;-webkit-columns:2;-moz-columns:2;columns:2;-moz-column-fill:auto;column-fill:auto\">");
config.reservedWords().forEach(s -> sb.append("<li>").append(escapeHtml4(s)).append("</li>").append(newline));
sb.append("</ul>");
sb.append(newline);
}
}

private void generateYamlSample(StringBuilder sb, CodegenConfig config) {

for (CliOption langCliOption : config.cliOptions()) {

sb.append("# Description: ").append(langCliOption.getDescription()).append(newline);

Map<String, String> enums = langCliOption.getEnum();
if (enums != null) {
sb.append("# Available Values:").append(newline);

for (Map.Entry<String, String> entry : enums.entrySet()) {
sb.append("# ").append(entry.getKey()).append(newline);
sb.append("# ").append(entry.getValue()).append(newline);
}
}

String defaultValue = langCliOption.getDefault();

if (defaultValue != null) {
sb.append(langCliOption.getOpt()).append(": ").append(defaultValue).append(newline);
} else {
sb.append("# ").append(langCliOption.getOpt()).append(": ").append(newline);
}

sb.append(newline);
}
}

private void generatePlainTextHelp(StringBuilder sb, CodegenConfig config) {
Expand All @@ -207,14 +289,112 @@ private void generatePlainTextHelp(StringBuilder sb, CodegenConfig config) {
}

sb.append(newline);
sb.append(newline);

String optIndent = "\t";
String optNestedIndent = "\t ";

for (CliOption langCliOption : config.cliOptions()) {
sb.append("\t").append(langCliOption.getOpt());
sb.append(optIndent).append(langCliOption.getOpt());
sb.append(newline);
sb.append(optNestedIndent).append(langCliOption.getOptionHelp()
.replaceAll("\n", System.lineSeparator() + optNestedIndent));
sb.append(newline);
sb.append(newline);
}

if (Boolean.TRUE.equals(importMappings)) {
sb.append(newline);
sb.append("IMPORT MAPPING");
sb.append(newline);
sb.append("\t ").append(langCliOption.getOptionHelp()
.replaceAll("\n", System.lineSeparator() + "\t "));
sb.append(newline);
Map<String, String> map = config.importMapping();
writePlainTextFromMap(sb, map, optIndent, optNestedIndent, "Type/Alias", "Imports");
sb.append(newline);
}

if (Boolean.TRUE.equals(instantiationTypes)) {
sb.append(newline);
sb.append("INSTANTIATION TYPES");
sb.append(newline);
sb.append(newline);
Map<String, String> map = config.instantiationTypes();
writePlainTextFromMap(sb, map, optIndent, optNestedIndent, "Type/Alias", "Instantiated By");
sb.append(newline);
}

if (Boolean.TRUE.equals(languageSpecificPrimitives)) {
sb.append(newline);
sb.append("LANGUAGE PRIMITIVES");
sb.append(newline);
sb.append(newline);
String[] arr = config.languageSpecificPrimitives().stream().sorted().toArray(String[]::new);
writePlainTextFromArray(sb, arr, optIndent);
sb.append(newline);
}

if (Boolean.TRUE.equals(reservedWords)) {
sb.append(newline);
sb.append("RESERVED WORDS");
sb.append(newline);
sb.append(newline);
String[] arr = config.reservedWords().stream().sorted().toArray(String[]::new);
writePlainTextFromArray(sb, arr, optIndent);
sb.append(newline);
}
}

private void writePlainTextFromMap(
StringBuilder sb,
Map<String, String> map,
String optIndent,
String optNestedIndent,
@SuppressWarnings("SameParameterValue") String keyHeader,
String valueHeader) {
if (map != null && map.size() > 0) {
int maxKey = keyHeader.length();
int maxValue = valueHeader.length();

for (Map.Entry<String, String> entry : map.entrySet()) {
String k = entry.getKey();
String v = entry.getValue();
maxKey = Math.max(maxKey, k.length());
maxValue = Math.max(maxValue, v.length());
}

String format = "%-" + maxKey + "s\t%-" + maxValue + "s";
sb.append(optIndent).append(String.format(Locale.ROOT, format, keyHeader, valueHeader));
sb.append(newline);
sb.append(optIndent).append(String.format(Locale.ROOT, format, StringUtils.repeat("-", maxKey), StringUtils.repeat("-", maxValue)));
map.forEach((key, value) -> {
sb.append(newline);
sb.append(optIndent).append(String.format(Locale.ROOT, format, key, value));
});
} else {
sb.append(optIndent).append("None");
}
}

private void writePlainTextFromArray(StringBuilder sb, String[] arr, String optIndent) {
if (arr.length > 0) {
// target a width of 20, then take the max up to 40.
int width = 20;
for (String s : arr) {
width = Math.max(width, Math.min(40, s.length()));
}

// do three columns if possible (assume terminal width ~90), otherwise do two columns.
int columns = width < 30 ? 3 : 2;
String format = "%-" + (90 / columns) + "s";
for (int i = 0; i < arr.length; i++) {
String current = arr[i];
sb.append(optIndent).append(String.format(Locale.ROOT, format, current));
if (i % columns == 0) {
sb.append(newline);
}
}
} else {
sb.append(optIndent).append("None");
}
}
}