mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-12-11 12:32:42 +00:00
[cli] Full config help details (#4928)
* [cli] Dump additional generator info via config-help (plain text) * [cli] Dump additional generator info via config-help (markdown)
This commit is contained in:
@@ -30,19 +30,21 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
|
import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
|
||||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
@Command(name = "config-help", description = "Config help for chosen lang")
|
@Command(name = "config-help", description = "Config help for chosen lang")
|
||||||
public class ConfigHelp implements Runnable {
|
public class ConfigHelp implements Runnable {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Generate.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(Generate.class);
|
||||||
|
|
||||||
public static final String FORMAT_TEXT = "text";
|
private static final String FORMAT_TEXT = "text";
|
||||||
public static final String FORMAT_MARKDOWN = "markdown";
|
private static final String FORMAT_MARKDOWN = "markdown";
|
||||||
public static final String FORMAT_YAMLSAMPLE = "yamlsample";
|
private static final String FORMAT_YAMLSAMPLE = "yamlsample";
|
||||||
|
|
||||||
@Option(name = {"-g",
|
@Option(name = {"-g",
|
||||||
"--generator-name"}, title = "generator name", description = "generator to get config help for")
|
"--generator-name"}, title = "generator name", description = "generator to get config help for")
|
||||||
@@ -61,18 +63,41 @@ public class ConfigHelp implements Runnable {
|
|||||||
FORMAT_TEXT, FORMAT_MARKDOWN, FORMAT_YAMLSAMPLE})
|
FORMAT_TEXT, FORMAT_MARKDOWN, FORMAT_YAMLSAMPLE})
|
||||||
private String format;
|
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 = {
|
@Option(name = {
|
||||||
"--markdown-header"}, title = "markdown header", description = "When format=markdown, include this option to write out markdown headers (e.g. for docusaurus).")
|
"--markdown-header"}, title = "markdown header", description = "When format=markdown, include this option to write out markdown headers (e.g. for docusaurus).")
|
||||||
private Boolean markdownHeader;
|
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();
|
private String newline = System.lineSeparator();
|
||||||
|
|
||||||
@Override public void run() {
|
@Override
|
||||||
|
public void run() {
|
||||||
if (isEmpty(generatorName)) {
|
if (isEmpty(generatorName)) {
|
||||||
LOGGER.error("[error] A generator name (--generator-name / -g) is required.");
|
LOGGER.error("[error] A generator name (--generator-name / -g) is required.");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(fullDetails)) {
|
||||||
|
instantiationTypes = Boolean.TRUE;
|
||||||
|
reservedWords = Boolean.TRUE;
|
||||||
|
languageSpecificPrimitives = Boolean.TRUE;
|
||||||
|
importMappings = Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
CodegenConfig config = CodegenConfigLoader.forName(generatorName);
|
CodegenConfig config = CodegenConfigLoader.forName(generatorName);
|
||||||
@@ -97,9 +122,9 @@ public class ConfigHelp implements Runnable {
|
|||||||
|
|
||||||
if (!isEmpty(outputFile)) {
|
if (!isEmpty(outputFile)) {
|
||||||
File out = Paths.get(outputFile).toFile();
|
File out = Paths.get(outputFile).toFile();
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
File parentFolder = out.getParentFile();
|
File parentFolder = out.getParentFile();
|
||||||
if (parentFolder != null && parentFolder.isDirectory()) {
|
if (parentFolder != null && parentFolder.isDirectory()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
parentFolder.mkdirs();
|
parentFolder.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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) {
|
private void generateMarkdownHelp(StringBuilder sb, CodegenConfig config) {
|
||||||
if (Boolean.TRUE.equals(markdownHeader)) {
|
if (Boolean.TRUE.equals(markdownHeader)) {
|
||||||
sb.append("---").append(newline);
|
sb.append("---").append(newline);
|
||||||
@@ -197,6 +194,91 @@ public class ConfigHelp implements Runnable {
|
|||||||
|
|
||||||
sb.append(newline);
|
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) {
|
private void generatePlainTextHelp(StringBuilder sb, CodegenConfig config) {
|
||||||
@@ -207,14 +289,112 @@ public class ConfigHelp implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sb.append(newline);
|
sb.append(newline);
|
||||||
|
sb.append(newline);
|
||||||
|
|
||||||
|
String optIndent = "\t";
|
||||||
|
String optNestedIndent = "\t ";
|
||||||
|
|
||||||
for (CliOption langCliOption : config.cliOptions()) {
|
for (CliOption langCliOption : config.cliOptions()) {
|
||||||
sb.append("\t").append(langCliOption.getOpt());
|
sb.append(optIndent).append(langCliOption.getOpt());
|
||||||
sb.append(newline);
|
sb.append(newline);
|
||||||
sb.append("\t ").append(langCliOption.getOptionHelp()
|
sb.append(optNestedIndent).append(langCliOption.getOptionHelp()
|
||||||
.replaceAll("\n", System.lineSeparator() + "\t "));
|
.replaceAll("\n", System.lineSeparator() + optNestedIndent));
|
||||||
sb.append(newline);
|
sb.append(newline);
|
||||||
sb.append(newline);
|
sb.append(newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(importMappings)) {
|
||||||
|
sb.append(newline);
|
||||||
|
sb.append("IMPORT MAPPING");
|
||||||
|
sb.append(newline);
|
||||||
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user