CliFlag.java
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2025, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.cli;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.Run;
import net.sourceforge.plantuml.preproc.Stdlib;
import net.sourceforge.plantuml.stats.StatsUtils;
import net.sourceforge.plantuml.swing.ClipboardLoop;
public enum CliFlag {
// General:
@CliFlagDoc(value = "Show help and usage information", level = 0)
HELP("--help", aliases("-h", "-?", DEPRECATED("-help")), Arity.UNARY_IMMEDIATE_ACTION, HelpPrint::printHelp),
@CliFlagDoc(value = "Show extended help (advanced options)", level = 0)
HELP_MORE("--help-more", aliases(DEPRECATED("-h:more"), DEPRECATED("-help:more")), Arity.UNARY_IMMEDIATE_ACTION,
HelpPrint::printHelpMore),
@CliFlagDoc(value = "Show PlantUML and Java version", level = 0)
VERSION("--version", aliases(DEPRECATED("-version")), Arity.UNARY_IMMEDIATE_ACTION, OptionPrint::printVersion),
@CliFlagDoc(value = "Show information about PlantUML authors", level = 0)
AUTHOR("--author", aliases("--about", DEPRECATED("-authors"), DEPRECATED("-about")), Arity.UNARY_IMMEDIATE_ACTION,
OptionPrint::printAbout), //
@CliFlagDoc(value = "Launch the graphical user interface", level = 0)
GUI("--gui", aliases(DEPRECATED("-gui")), Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.GUI, true)),
@CliFlagDoc(value = "Render diagrams in dark mode", level = 0)
DARK_MODE("--dark-mode", aliases(DEPRECATED("-darkmode")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Enable verbose logging", level = 0)
VERBOSE("--verbose", aliases(DEPRECATED("-v"), DEPRECATED("-verbose")), Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.VERBOSE, true)),
@CliFlagDoc(value = "Print total processing time", level = 0)
DURATION("--duration", aliases(DEPRECATED("-duration")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Show a textual progress bar", level = 0)
PROGRESS("--progress-bar", aliases(DEPRECATED("-progress")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Show splash screen with progress bar", level = 0)
SPLASH("--splash-screen", aliases(DEPRECATED("-splash")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Check Graphviz installation", level = 0)
TEST_DOT("--check-graphviz", aliases(DEPRECATED("-testdot")), Arity.UNARY_IMMEDIATE_ACTION,
OptionPrint::printCheckGraphviz),
@CliFlagDoc(value = "Start internal HTTP server for rendering (default port : 4242)", usage = "--http-server[:<port>]", level = 0)
PICOWEB("--http-server", aliases(DEPRECATED("-picoweb")), Arity.UNARY_OPTIONAL_COLON),
// Input & preprocessing:
@CliFlagDoc(value = "Exclude input files matching the given pattern", usage = "--exclude <pattern>", level = 1, newGroup = "Input & preprocessing")
EXCLUDE("--exclude", aliases("-x", DEPRECATED("-exclude")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Read source from stdin, write result to stdout", level = 0)
PIPE("--pipe", aliases("-p", DEPRECATED("-pipe")), Arity.UNARY_BOOLEAN),
PIPEMAP("-pipemap", Arity.UNARY_BOOLEAN), //
PIPEDELIMITOR("-pipedelimitor", Arity.BINARY_NEXT_ARGUMENT_VALUE), //
PIPENOSTDERR("-pipenostderr", Arity.UNARY_BOOLEAN), //
@CliFlagDoc("Generate the Nth image with pipe option")
@CliDefaultValue("0")
PIPE_IMAGE_INDEX("--pipe-image-index", aliases(DEPRECATED("-pipeimageindex")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Define a preprocessing variable (equivalent to '!define <var> <value>')", usage = "-d, --define <VAR>=<value>", level = 0)
DEFINE("-D", Arity.UNARY_INLINE_KEY_OR_KEY_VALUE), //
DEFINE_LONG("--define", Arity.BINARY_NEXT_ARGUMENT_VALUE), //
@CliFlagDoc(value = "Include external file (as with '!include <file>')", usage = "-I, --include <file>", level = 1)
INCLUDE("-I", Arity.UNARY_INLINE_KEY_OR_KEY_VALUE), //
INCLUDE_LONG("--include", Arity.BINARY_NEXT_ARGUMENT_VALUE), //
@CliFlagDoc(value = "Set pragma (equivalent to '!pragma <key> <value>')", usage = "-P, --pragma <key>=<value>", level = 1)
PRAGMA("-P", Arity.UNARY_INLINE_KEY_OR_KEY_VALUE), //
PRAGMA_LONG("--pragma", Arity.BINARY_NEXT_ARGUMENT_VALUE), //
@CliFlagDoc(value = "Set skin parameter (equivalent to 'skinparam <key> <value>')", usage = "--skinparam <key>=<value>", level = 1)
SKINPARAM("-S", Arity.UNARY_INLINE_KEY_OR_KEY_VALUE), //
SKINPARAM_LONG("--skinparam", Arity.BINARY_NEXT_ARGUMENT_VALUE), //
@CliFlagDoc(value = "Apply a theme", usage = "--theme <name>", level = 1)
THEME("--theme", aliases(DEPRECATED("-theme")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Specify configuration file", usage = "--config <file>", level = 1)
CONFIG("--config", aliases(DEPRECATED("-config")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Use a specific input charset", usage = "--charset <name>", level = 1)
@CliDefaultValue("UTF-8")
CHARSET("--charset", aliases(DEPRECATED("-charset")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
// Execution control:
@CliFlagDoc(value = "Check diagram syntax without generating images", level = 0, newGroup = "Execution control")
CHECK_ONLY("--check-syntax", aliases("--syntax-check", DEPRECATED("-checkonly")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Stop at the first syntax error", level = 0)
FAIL_FAST("--stop-on-error", aliases(DEPRECATED("-failfast")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Pre-check syntax of all inputs and stop faster on error", level = 0)
FAIL_FAST2("--check-before-run", aliases(DEPRECATED("-failfast2")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Do not generate error images for diagrams with syntax errors", level = 0)
NO_ERROR_IMAGE("--no-error-image", aliases(DEPRECATED("-noerror")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Set Graphviz processing timeout (in seconds)", usage = "--graphviz-timeout <seconds>", level = 1)
TIMEOUT("--graphviz-timeout", aliases(DEPRECATED("-timeout")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Use <n> threads for processing (auto = available processors)", usage = "--threads <n|auto>", level = 1)
NB_THREAD("--threads", aliases(DEPRECATED("-nbthread")), Arity.BINARY_NEXT_ARGUMENT_VALUE),
// Metadata & assets:
@CliFlagDoc(value = "Extract embedded PlantUML source from PNG or SVG metadata", level = 0, newGroup = "Metadata & assets")
RETRIEVE_METADATA("--extract-source", aliases(DEPRECATED("-metadata")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Do not include metadata in generated files", level = 1)
NO_METADATA("--disable-metadata", aliases(DEPRECATED("-nometadata")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Skip PNG/SVG files that are already up-to-date (using metadata)", level = 0)
CHECK_METADATA("--skip-fresh", aliases(DEPRECATED("-checkmetadata")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Encode a sprite definition from an image file", usage = "--sprite <4|8|16[z]> <file>", level = 0)
ENCODE_SPRITE("--encode-sprite", aliases(DEPRECATED("-sprite"), DEPRECATED("-encodesprite")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Generate an encoded PlantUML URL from a source file", level = 1)
COMPUTE_URL("--encode-url", aliases("--compute-url", DEPRECATED("-computeurl"), DEPRECATED("-encodeurl")),
Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Decode a PlantUML encoded URL back to its source", usage = "--decode-url <string>", level = 1)
DECODE_URL("--decode-url", aliases(DEPRECATED("-decodeurl")), Arity.UNARY_BOOLEAN),
@CliFlagDoc(value = "Print the list of PlantUML language keywords", level = 1)
LANGUAGE("--list-keywords", aliases(DEPRECATED("-language")), Arity.UNARY_IMMEDIATE_ACTION,
OptionPrint::printListKeywords),
@CliFlagDoc(value = "Specify the path to the Graphviz 'dot' executable", usage = "--dot-path <path-to-dot-exe>", level = 1)
GRAPHVIZ_DOT("--dot-path", aliases(DEPRECATED("-graphvizdot"), DEPRECATED("-graphviz_dot")),
Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Start a local FTP server for diagram rendering (rarely used)", level = 1)
FTP("--ftp-server", aliases(DEPRECATED("-ftp")), Arity.UNARY_OPTIONAL_COLON),
// Output control
@CliFlagDoc(value = "Generate output files in the specified directory", usage = "--output-dir <dir>", level = 1, newGroup = "Output control")
OUTPUT_DIR("--output-dir", aliases("-o", DEPRECATED("output_dir"), DEPRECATED("-output"), DEPRECATED("-odir")),
Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Allow overwriting of read-only output files", level = 1)
OVERWRITE("--overwrite", aliases("--force-overwrite", DEPRECATED("-overwrite")), Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.OVERWRITE, true)),
// Other
CLIPBOARD("--clipboard", Arity.UNARY_IMMEDIATE_ACTION, ClipboardLoop::runOnce), //
CLIPBOARDLOOP("--clipboardloop", Arity.UNARY_IMMEDIATE_ACTION, ClipboardLoop::runLoop), //
@CliFlagDoc("Generate intermediate Svek files")
DEBUG_SVEK("-debugsvek", aliases("-debug_svek"), Arity.UNARY_BOOLEAN),
@CliFlagDoc("Pretend input files are located in given directory")
FILE_DIR("-filedir", Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc("Override %filename% variable")
FILENAME("-filename", Arity.BINARY_NEXT_ARGUMENT_VALUE),
HEADLESS("-headless", Arity.UNARY_BOOLEAN, () -> System.setProperty("java.awt.headless", "true")),
@CliFlagDoc("List fonts available on your system")
PRINT_FONTS("-printfonts", Arity.UNARY_IMMEDIATE_ACTION, Run::printFonts),
@CliFlagDoc("Print standard library information")
STD_LIB("-stdlib", Arity.UNARY_IMMEDIATE_ACTION, Stdlib::printStdLib),
STDRPT("-stdrpt", Arity.UNARY_OPTIONAL_COLON),
@CliFlagDoc("Report syntax errors from stdin without generating images")
SYNTAX("-syntax", Arity.UNARY_BOOLEAN),
LICENSE("-license", aliases("-licence"), Arity.UNARY_IMMEDIATE_ACTION, OptionPrint::printLicense),
WORD("-word", Arity.UNARY_BOOLEAN, () -> GlobalConfig.getInstance().put(GlobalConfigKey.WORD, true)),
USE_SEPARATOR_MINUS("-useseparatorminus", Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.FILE_SEPARATOR, "-")),
// Output format (choose one)
@CliFlagDoc(value = "Set the output format for generated diagrams\n(e.g. png, svg, pdf, eps, latex, txt, utxt, obfuscate, preproc...)", level = 0, usage = "-f, --format <name>", newGroup = "Output format (choose one)")
FORMAT("--format", aliases("-f"), Arity.BINARY_NEXT_ARGUMENT_VALUE),
@CliFlagDoc(value = "Generate images in EPS format", level = 0, newGroup = "Available formats")
T_EPS("--eps", aliases(DEPRECATED("-teps"), DEPRECATED("-eps")), Arity.UNARY_BOOLEAN, FileFormat.EPS),
T_EPS_TEXT("--teps:text", aliases(DEPRECATED("-teps:text"), DEPRECATED("-eps:text")), Arity.UNARY_BOOLEAN,
FileFormat.EPS_TEXT),
@CliFlagDoc(value = "Generate HTML files for class diagrams", level = 1)
T_HTML("--html", aliases(DEPRECATED("-thtml"), DEPRECATED("-html")), Arity.UNARY_BOOLEAN, FileFormat.HTML),
@CliFlagDoc(value = "Generate LaTeX/TikZ output", level = 0)
T_LATEX("--latex", aliases(DEPRECATED("-tlatex"), DEPRECATED("-latex")), Arity.UNARY_BOOLEAN, FileFormat.LATEX),
@CliFlagDoc(value = "Generate LaTeX/TikZ output without preamble", level = 1)
T_LATEX_NOPREAMBLE("--latex-nopreamble", aliases(DEPRECATED("-tlatex:nopreamble"), DEPRECATED("-latex:nopreamble")),
Arity.UNARY_BOOLEAN, FileFormat.LATEX_NO_PREAMBLE),
@CliFlagDoc(value = "Replace text in diagrams with obfuscated strings to share diagrams safely", level = 0)
OBFUSCATE("--obfuscate", aliases(DEPRECATED("-cypher")), Arity.UNARY_BOOLEAN, FileFormat.OBFUSCATE),
@CliFlagDoc(value = "Generate PDF images", level = 1)
T_PDF("--pdf", aliases(DEPRECATED("-tpdf"), DEPRECATED("-pdf")), Arity.UNARY_BOOLEAN, FileFormat.PDF),
@CliFlagDoc(value = "Generate PNG images (default)", level = 0)
T_PNG("--png", aliases(DEPRECATED("-tpng"), DEPRECATED("-png")), Arity.UNARY_BOOLEAN, FileFormat.PNG),
@CliFlagDoc(value = "Generate the preprocessed source after applying !include, !define... (no rendering)", level = 0)
PREPROCESS("--preproc", aliases(DEPRECATED("-preproc")), Arity.UNARY_BOOLEAN, FileFormat.PREPROC),
@CliFlagDoc(value = "Generate SCXML files for state diagrams", level = 1)
T_SCXML("--scxml", aliases(DEPRECATED("-tscxml")), Arity.UNARY_BOOLEAN, FileFormat.SCXML),
@CliFlagDoc(value = "Generate SVG images", level = 0)
T_SVG("--svg", aliases(DEPRECATED("-tsvg"), DEPRECATED("-svg")), Arity.UNARY_BOOLEAN, FileFormat.SVG),
@CliFlagDoc(value = "Generate ASCII art diagrams", level = 0)
T_TXT("--txt", aliases(DEPRECATED("-ttxt"), DEPRECATED("-txt")), Arity.UNARY_BOOLEAN, FileFormat.ATXT),
@CliFlagDoc(value = "Generate ASCII art diagrams using Unicode characters", level = 0)
T_UTXT("--utxt", aliases(DEPRECATED("-tutxt"), DEPRECATED("-utxt")), Arity.UNARY_BOOLEAN, FileFormat.UTXT),
@CliFlagDoc(value = "Generate VDX files", level = 1)
T_VDX("--vdx", aliases(DEPRECATED("-tvdx"), DEPRECATED("-vdx")), Arity.UNARY_BOOLEAN, FileFormat.VDX),
@CliFlagDoc(value = "Generate XMI files for class diagrams", level = 1)
T_XMI("--xmi", aliases(DEPRECATED("-txmi"), DEPRECATED("-xmi")), Arity.UNARY_BOOLEAN, FileFormat.XMI_STANDARD),
T_XMI_ARGO("--txmi:argo", aliases(DEPRECATED("-xmi:argo")), Arity.UNARY_BOOLEAN, FileFormat.XMI_ARGO),
T_XMI_CUSTOM("--txmi:custom", aliases(DEPRECATED("-xmi:custom")), Arity.UNARY_BOOLEAN, FileFormat.XMI_CUSTOM),
T_XMI_SCRIPT("--txmi:script", aliases(DEPRECATED("-xmi:script")), Arity.UNARY_BOOLEAN, FileFormat.XMI_SCRIPT),
T_XMI_STAR("--txmi:star", aliases(DEPRECATED("-xmi:star")), Arity.UNARY_BOOLEAN, FileFormat.XMI_STAR),
T_BASE64("--tbase64", Arity.UNARY_BOOLEAN, FileFormat.BASE64),
T_BRAILLE("--tbraille", Arity.UNARY_BOOLEAN, FileFormat.BRAILLE_PNG),
// ************************ stats
@CliFlagDoc(value = "Disable statistics collection (default behavior)", level = 1, newGroup = "Statistics")
DISABLE_STATS("--disable-stats", aliases(DEPRECATED("-disablestats")), Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.ENABLE_STATS, false)),
@CliFlagDoc(value = "Enable statistics collection", level = 1)
ENABLE_STATS("--enable-stats", aliases(DEPRECATED("-enablestats")), Arity.UNARY_BOOLEAN,
() -> GlobalConfig.getInstance().put(GlobalConfigKey.ENABLE_STATS, true)),
@CliFlagDoc(value = "Export collected statistics to an HTML report and exit", level = 1)
DUMPHTMLSTATS("--export-stats-html", Arity.UNARY_IMMEDIATE_ACTION, StatsUtils::outHtml),
@CliFlagDoc(value = "Export collected statistics to a text report and exit", level = 1)
DUMPSTATS("--export-stats", Arity.UNARY_IMMEDIATE_ACTION, StatsUtils::dumpStats),
@CliFlagDoc(value = "Output general statistics in HTML format", level = 1)
HTML_STATS("--html-stats", aliases(DEPRECATED("-htmlstats")), Arity.UNARY_BOOLEAN,
() -> StatsUtils.setHtmlStats(true)),
@CliFlagDoc(value = "Output general statistics in XML format", level = 1)
XML_STATS("--xml-stats", aliases(DEPRECATED("-xmlstats")), Arity.UNARY_BOOLEAN, () -> StatsUtils.setXmlStats(true)),
@CliFlagDoc(value = "Generate statistics in real time during processing", level = 1)
REALTIME_STATS("--realtime-stats", aliases(DEPRECATED("-realtimestats")), Arity.UNARY_BOOLEAN,
() -> StatsUtils.setRealTimeStats(true)),
@CliFlagDoc(value = "Continuously print usage statistics during execution", level = 1)
LOOP_STATS("--loop-stats", aliases(DEPRECATED("-loopstats")), Arity.UNARY_IMMEDIATE_ACTION, StatsUtils::loopStats);
private final String flag;
private final List<String> aliases;
private final Arity type;
private final Object foo;
CliFlag(String flag, Arity type) {
this(flag, Collections.emptyList(), type, null);
}
CliFlag(String flag, List<String> aliases, Arity type) {
this(flag, aliases, type, null);
}
CliFlag(String flag, Arity type, CliAction foo) {
this(flag, Collections.emptyList(), type, foo);
}
CliFlag(String flag, Arity type, Object foo) {
this(flag, Collections.emptyList(), type, foo);
}
CliFlag(String flag, List<String> aliases, Arity type, Object foo) {
this.type = type;
this.flag = flag;
this.aliases = aliases;
this.foo = foo;
}
CliFlag(String flag, List<String> aliases, Arity type, CliAction foo) {
this.type = type;
this.flag = flag;
this.aliases = aliases;
this.foo = foo;
}
private static List<String> aliases(String... names) {
return Arrays.asList(names);
}
private static String DEPRECATED(String option) {
return option;
}
public String getFlag() {
return flag;
}
public List<String> getAliases() {
return aliases;
}
public Arity getType() {
return type;
}
boolean match(String tmp) {
if (type == Arity.UNARY_INLINE_KEY_OR_KEY_VALUE || type == Arity.UNARY_OPTIONAL_COLON) {
for (String alias : aliases)
if (tmp.startsWith(alias))
return true;
return tmp.startsWith(flag);
}
for (String alias : aliases)
if (tmp.equals(alias))
return true;
return tmp.equals(flag);
}
public String getFlagDoc() {
try {
final CliFlagDoc annotation = CliFlag.class.getField(this.name()).getAnnotation(CliFlagDoc.class);
if (annotation != null && !annotation.value().isEmpty())
return annotation.value();
} catch (NoSuchFieldException e) {
// Should never happen for enum constants
}
return null;
}
public String getNewgroup() {
try {
final CliFlagDoc annotation = CliFlag.class.getField(this.name()).getAnnotation(CliFlagDoc.class);
if (annotation != null && !annotation.value().isEmpty())
return annotation.newGroup();
} catch (NoSuchFieldException e) {
// Should never happen for enum constants
}
return "";
}
public String getUsage() {
try {
final CliFlagDoc annotation = CliFlag.class.getField(this.name()).getAnnotation(CliFlagDoc.class);
if (annotation != null && !annotation.usage().isEmpty()) {
final String usage = annotation.usage();
if (usage.startsWith("--"))
return " " + usage;
return " " + usage;
}
} catch (NoSuchFieldException e) {
// Should never happen for enum constants
}
for (String alias : aliases)
if (alias.length() == 2)
return " " + alias + ", " + getFlag();
return " " + getFlag();
}
public int getFlagLevel() {
try {
final CliFlagDoc annotation = CliFlag.class.getField(this.name()).getAnnotation(CliFlagDoc.class);
if (annotation != null)
return annotation.level();
} catch (NoSuchFieldException e) {
// Should never happen for enum constants
}
return -1;
}
public String getDefaultValue() {
try {
final CliDefaultValue annotation = CliFlag.class.getField(this.name()).getAnnotation(CliDefaultValue.class);
if (annotation != null && !annotation.value().isEmpty())
return annotation.value();
} catch (NoSuchFieldException e) {
// Should never happen for enum constants
}
return null;
}
public Object getFoo() {
return foo;
}
}