diff --git a/.gitignore b/.gitignore
index 003bae80f..c97d5920d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,6 @@ allure-results
.DS_Store
.env
assets/
+.cachebro/
+CLAUDE.md
+PLAN-*.md
diff --git a/build.gradle b/build.gradle
index c1b52f385..1d3b4adee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -156,8 +156,11 @@ dependencies {
implementation 'org.jspecify:jspecify:1.0.0'
implementation 'org.apache.commons:commons-text:1.15.0'
implementation 'org.apache.commons:commons-compress:1.27.1'
- implementation 'info.picocli:picocli:4.7.7'
- annotationProcessor 'info.picocli:picocli-codegen:4.7.7'
+ implementation('org.aesh:aesh:3.8-dev') {
+ exclude group: 'org.aesh', module: 'readline'
+ }
+ implementation 'org.aesh:readline-api:3.7'
+ annotationProcessor 'org.aesh:aesh-processor:3.8-dev'
implementation 'io.quarkus.qute:qute-core:1.13.7.Final'
implementation 'org.codehaus.plexus:plexus-java:1.2.0'
implementation 'com.google.code.gson:gson:2.13.2'
@@ -387,7 +390,9 @@ shadowJar {
}
test {
- useJUnitPlatform()
+ useJUnitPlatform() {
+ excludeTags 'benchmark'
+ }
javaLauncher = testExecutionToolchain
def jvmArgsList = ["-javaagent:${configurations.agent.singleFile}"] // for allure reporting
if (testJavaVersion.asInt() >= 9) {
@@ -413,6 +418,25 @@ test {
systemProperty('jbang.test.wiremock.enable', project.findProperty('disableWiremock') == 'true' ? 'false' : 'true')
}
+task benchmark(type: Test) {
+ description = 'Run startup benchmark tests'
+ group = 'verification'
+ useJUnitPlatform() {
+ includeTags 'benchmark'
+ }
+ javaLauncher = testExecutionToolchain
+ def jvmArgsList = []
+ if (testJavaVersion.asInt() >= 9) {
+ jvmArgsList.addAll([
+ "--add-opens", "java.base/java.lang=ALL-UNNAMED",
+ "--add-opens", "java.base/java.util=ALL-UNNAMED"
+ ])
+ }
+ jvmArgs = jvmArgsList
+ testLogging.showStandardStreams = true
+ systemProperty('jbang.test.wiremock.enable', project.findProperty('disableWiremock') == 'true' ? 'false' : 'true')
+}
+
jacoco {
toolVersion = '0.8.14' // 0.8.14 supports java 25
}
@@ -606,7 +630,7 @@ asciidoctor {
task clidoc(type: Exec) {
doFirst {
println 'Generating cli man pages'
- commandLine 'build/install/jbang/bin/jbang', '--cp', 'build/install/jbang/bin/jbang.jar', '--deps','org.eclipse.sisu:org.eclipse.sisu.inject:0.3.5', 'docs/genadoc.java', '-d', 'docs/modules/cli', '--force', 'dev.jbang.cli.JBang'
+ commandLine 'build/install/jbang/bin/jbang', '--cp', 'build/install/jbang/bin/jbang.jar', 'docs/genadoc.java', '-d', 'docs/modules/cli', '--force', 'dev.jbang.cli.JBang'
}
}
diff --git a/docs/genadoc.java b/docs/genadoc.java
index b61983c09..a3e137629 100644
--- a/docs/genadoc.java
+++ b/docs/genadoc.java
@@ -1,935 +1,378 @@
-//DEPS info.picocli:picocli:4.7.7
-//DEPS info.picocli:picocli-codegen:4.7.7
+///usr/bin/env jbang "$0" "$@" ; exit $?
+//DEPS org.aesh:aesh:3.8-dev
+//DEPS org.aesh:readline-api:3.7
///COMPILE_OPTIONS -proc:none
//JAVA 17+
-import picocli.CommandLine;
-import picocli.CommandLine.Command;
-import picocli.CommandLine.Help.Ansi.IStyle;
-import picocli.CommandLine.Help.Ansi.Style;
-import picocli.CommandLine.Help.Ansi.Text;
-import picocli.CommandLine.Help.ColorScheme;
-import picocli.CommandLine.Help.IOptionRenderer;
-import picocli.CommandLine.Help.IParamLabelRenderer;
-import picocli.CommandLine.Help.IParameterRenderer;
-import picocli.CommandLine.Mixin;
-import picocli.CommandLine.Model.ArgGroupSpec;
-import picocli.CommandLine.Model.CommandSpec;
-import picocli.CommandLine.Model.IOrdered;
-import picocli.CommandLine.Model.OptionSpec;
-import picocli.CommandLine.Model.PositionalParamSpec;
-import picocli.CommandLine.Option;
-import picocli.CommandLine.Parameters;
-import picocli.CommandLine.Spec;
-import picocli.codegen.util.Assert;
-import picocli.codegen.util.Util;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.lang.reflect.Method;
+import org.aesh.command.Command;
+import org.aesh.command.CommandDefinition;
+import org.aesh.command.GroupCommandDefinition;
+import org.aesh.command.impl.container.AeshCommandContainerBuilder;
+import org.aesh.command.impl.internal.ProcessedCommand;
+import org.aesh.command.impl.internal.ProcessedOption;
+import org.aesh.command.impl.internal.OptionType;
+import org.aesh.command.impl.parser.AeshCommandLineParser;
+import org.aesh.command.impl.parser.CommandLineParser;
+import org.aesh.command.container.CommandContainer;
+
+import java.io.*;
+import java.nio.file.*;
import java.util.*;
-import java.util.concurrent.Callable;
+import java.util.stream.*;
import static java.lang.String.format;
/**
- * Generates AsciiDoc files in a special format that can be converted to HTML,
- * PDF and Unix Man pages.
- *
- * This class can be used as a subcommand, in which case it generates man pages
- * for all non-hidden commands in the hierarchy from the top-level command down,
- * or it can be executed as a stand-alone tool, in which case the user needs to
- * specify the {@code @Command}-annotated classes to generate man pages for.
- *
+ * Generates AsciiDoc man pages from aesh command metadata.
+ * Produces the same output format as the previous picocli-based generator.
+ *
+ * Usage: jbang docs/genadoc.java -d docs/modules/cli --force dev.jbang.cli.JBang
*/
-@Command(name = "gen-adoc", version = "${COMMAND-FULL-NAME} " + CommandLine.VERSION, helpCommand = true, // don't
- // validate
- // required
- // options and
- // positional
- // parameters
- // of the
- // parent
- // command
- showAtFileInUsageHelp = true, mixinStandardHelpOptions = true, sortOptions = false, usageHelpAutoWidth = true, usageHelpWidth = 100, description = {
- "Generates asciidoc pages for all commands in the specified directory." },
- // exitCodeListHeading = "%nExit Codes (if enabled with `--exit`)%n",
- // exitCodeList = {
- // "0:Successful program execution.",
- // "1:A runtime exception occurred while generating man pages.",
- // "2:Usage error: user input for the command was incorrect, " +
- // "e.g., the wrong number of arguments, a bad flag, " +
- // "a bad syntax in a parameter, etc.",
- // "4:A template file exists in the template directory. (Remove the
- // `--template-dir` option or use `--force` to overwrite.)"
- // },
- footerHeading = "%nConverting to asciidoc Format%n%n", footer = {
- "Use the `asciidoctor` tool to convert the generated AsciiDoc files to html: ", "",
- "`asciidoctor --backend=manpage --source-dir=SOURCE_DIR --destination-dir=DESTINATION *.adoc`", "",
- "Point the SOURCE_DIR to either the `--outdir` directory or the `--template-dir` directory. Use some other directory as the DESTINATION.",
- "See https://asciidoctor.org/docs/user-manual/#man-pages",
- "See http://man7.org/linux/man-pages/man7/roff.7.html", })
-public class genadoc implements Callable {
- static final int EXIT_CODE_TEMPLATE_EXISTS = 4;
-
- static final IStyle BOLD = new IStyle() {
- public String on() {
- return "*";
- }
-
- public String off() {
- return "*";
- }
- };
- static final IStyle ITALIC = new IStyle() {
- public String on() {
- return "_";
- }
-
- public String off() {
- return "_";
- }
- };
- static final IStyle HIGHLIGHT = new IStyle() {
- public String on() {
- return "#";
- }
-
- public String off() {
- return "#";
- }
- };
- static final ColorScheme COLOR_SCHEME = new ColorScheme.Builder(CommandLine.Help.Ansi.ON).commands(BOLD)
- .options(BOLD).optionParams(ITALIC).parameters(ITALIC).customMarkupMap(createMarkupMap()).build();
-
- static final ColorScheme PLAIN_SCHEME = new ColorScheme.Builder(CommandLine.Help.Ansi.ON).options(BOLD)
- .optionParams(ITALIC).parameters(ITALIC).customMarkupMap(createMarkupMap()).build();
- @Mixin
- Config config;
- @Spec
- CommandSpec spec;
-
- /**
- * Invokes {@link #generateManPage(Config, CommandLine.Model.CommandSpec...)} to
- * generate man pages for all non-hidden commands in the hierarchy from the
- * top-level command down. This method is only called when this class is used as
- * a subcommand.
- *
- * @return an exit code indicating success or failure, as follows:
- *
- * - 0: Successful program execution.
- * - 1: A runtime exception occurred while generating man pages.
- * - 2: Usage error: user input for the command was incorrect, e.g.,
- * the wrong number of arguments, a bad flag, a bad syntax in a
- * parameter, etc.
- * - 4: A template file exists in the template directory. (Remove the
- * `--template-dir` option or use `--force` to overwrite.)
- *
- * @throws IOException if a problem occurred writing files.
- */
- public Integer call() throws IOException {
- return generateManPage(config, spec.root());
- }
-
- private static Map createMarkupMap() {
- Map result = new HashMap();
- result.put(Style.bold.name(), BOLD);
- result.put(Style.italic.name(), ITALIC);
- result.put(Style.underline.name(), ITALIC);
- result.put(Style.reverse.name(), HIGHLIGHT);
- return result;
- }
-
- static class Config {
- @Option(names = { "-d", "--outdir" }, defaultValue = ".", paramLabel = "", description = {
- "Output directory to write the generated AsciiDoc files to. "
- + "If not specified, files are written to the current directory." })
- File directory;
-
- @Option(names = { "-t", "--template-dir" }, paramLabel = "", description = {
- "Optional directory to write customizable man page template files. "
- + "If specified, an additional \"template\" file is created here for each "
- + "generated manpage AsciiDoc file. ",
- "Each template file contains `include` directives that import content "
- + "from the corresponding generated manpage AsciiDoc file in the `--outdir` directory. "
- + "Text can be added after each include to customize the resulting man page. "
- + "The resulting man page will be a mixture of generated and manually edited text.",
- "These customizable templates are intended to be generated once, and afterwards "
- + "be manually updated and maintained." })
- File templatesDirectory;
-
- @Option(names = { "-v", "--verbose" }, description = { "Specify multiple -v options to increase verbosity.",
- "For example, `-v -v -v` or `-vvv`" })
- boolean[] verbosity = new boolean[0];
-
- @Option(names = { "-f",
- "--force" }, negatable = true, description = { "Overwrite existing man page templates. "
- + "The default is `--no-force`, meaning processing is aborted and the process exits "
- + "with status code 4 if a man page template file already exists." })
- boolean force;
-
- @Option(names = { "--component-root" }, description = { "The prefix/component of the xref links." }, defaultValue = "jbang:cli:")
- String componentRoot;
-
- private void verbose(String message, Object... params) {
- if (verbosity.length > 0) {
- System.err.printf(message, params);
- }
- }
-
- private void verboseDetailed(String message, Object... params) {
- if (verbosity.length > 1) {
- System.err.printf(message, params);
+public class genadoc {
+
+ static String componentRoot = "jbang:cli:";
+
+ public static void main(String[] args) throws Exception {
+ String outDir = ".";
+ boolean force = false;
+ String className = null;
+
+ for (int i = 0; i < args.length; i++) {
+ switch (args[i]) {
+ case "-d":
+ case "--outdir":
+ outDir = args[++i];
+ break;
+ case "--force":
+ case "-f":
+ force = true;
+ break;
+ case "--component-root":
+ componentRoot = args[++i];
+ break;
+ default:
+ className = args[i];
}
}
- }
-
- @Command(name = "gen-manpage", version = "picocli-codegen ${COMMAND-NAME} "
- + CommandLine.VERSION, showAtFileInUsageHelp = true, mixinStandardHelpOptions = true, sortOptions = false, usageHelpAutoWidth = true, usageHelpWidth = 100, description = {
- "Generates one or more AsciiDoc files with doctype 'manpage' in the specified directory." }, exitCodeListHeading = "%nExit Codes (if enabled with `--exit`)%n", exitCodeList = {
- "0:Successful program execution.",
- "1:A runtime exception occurred while generating man pages.",
- "2:Usage error: user input for the command was incorrect, "
- + "e.g., the wrong number of arguments, a bad flag, "
- + "a bad syntax in a parameter, etc.",
- "4:A template file exists in the template directory. (Remove the `--template-dir` option or use `--force` to overwrite.)" }, footerHeading = "%nConverting to Man Page Format%n%n", footer = {
- "Use the `asciidoctor` tool to convert the generated AsciiDoc files to man pages in roff format:",
- "",
- "`asciidoctor --backend=manpage --source-dir=SOURCE_DIR --destination-dir=DESTINATION *.adoc`",
- "",
- "Point the SOURCE_DIR to either the `--outdir` directory or the `--template-dir` directory. Use some other directory as the DESTINATION.",
- "See https://asciidoctor.org/docs/user-manual/#man-pages",
- "See http://man7.org/linux/man-pages/man7/roff.7.html", "",
- "In order to generate localized man pages, set the target locale by specifying the user.language, user.country, and user.variant system properties.",
- "The generated usage help will then contain information retrieved from the resource bundle based on the user locale.",
- "", "Example", "-------",
- " java -Duser.language=de -cp \"myapp.jar;picocli-4.6.2-SNAPSHOT.jar;picocli-codegen-4.6.2-SNAPSHOT.jar\" "
- + "picocli.codegen.docgen.manpage.ManPageGenerator my.pkg.MyClass" })
- private static class App implements Callable {
-
- @Parameters(arity = "1..*", description = "One or more command classes to generate man pages for.")
- Class>[] classes = new Class>[0];
-
- @Mixin
- Config config;
-
- @Option(names = { "-c",
- "--factory" }, description = "Optionally specify the fully qualified class name of the custom factory to use to instantiate the command class. "
- + "If omitted, the default picocli factory is used.")
- String factoryClass;
-
- @Option(names = "--exit", negatable = true, description = "Specify `--exit` if you want the application to call `System.exit` when finished. "
- + "By default, `System.exit` is not called.")
- boolean exit;
-
- public Integer call() throws Exception {
- List specs = Util.getCommandSpecs(factoryClass, classes);
- generateNavPage(config, specs.get(0));
- return generateManPage(config, specs.toArray(new CommandSpec[0]));
- }
- }
-
- /**
- * Invokes {@link #generateManPage(Config, CommandLine.Model.CommandSpec...)} to
- * generate man pages for the user-specified {@code @Command}-annotated classes.
- *
- * If the {@code --exit} option is specified, {@code System.exit} is invoked
- * afterwards with an exit code as follows:
- *
- *
- * - 0: Successful program execution.
- * - 1: A runtime exception occurred while generating man pages.
- * - 2: Usage error: user input for the command was incorrect, e.g., the wrong
- * number of arguments, a bad flag, a bad syntax in a parameter, etc.
- * - 4: A template file exists in the template directory. (Remove the
- * `--template-dir` option or use `--force` to overwrite.)
- *
- *
- *
- *
- *
- *
- * @param args command line arguments to be parsed. Must include the classes to
- * generate man pages for.
- */
- public static void main(String[] args) {
- App app = new App();
- int exitCode = new CommandLine(app).execute(args);
- if (app.exit) {
- System.exit(exitCode);
- }
- }
-
- /**
- * Generates AsciiDoc files for the specified classes to the specified output
- * directory, optionally also generating template files in the
- * {@code customizablePagesDirectory} directory.
- *
- * @param outdir Output directory to write the generated
- * AsciiDoc files to.
- * @param customizablePagesDirectory Optional directory to write customizable
- * man page template files. If
- * non-{@code null}, an additional "template"
- * file is created here for each generated
- * manpage AsciiDoc file.
- * @param verbosity the length of this array determines
- * verbosity during processing
- * @param overwriteCustomizablePages Overwrite existing man page templates. The
- * default is false, meaning processing is
- * aborted and the process exits with status
- * code 4 if a man page template file already
- * exists.
- * @param specs the Commands to generate AsciiDoc man pages
- * for
- * @return the exit code
- * @throws IOException if a problem occurred writing to the file system
- */
- public static int generateManPage(File outdir, File customizablePagesDirectory, boolean[] verbosity,
- boolean overwriteCustomizablePages, CommandSpec... specs) throws IOException {
- Config config = new Config();
- config.directory = outdir;
- config.templatesDirectory = customizablePagesDirectory;
- config.verbosity = verbosity;
- config.force = overwriteCustomizablePages;
-
- return generateManPage(config, specs);
- }
-
- static int generateManPage(Config config, CommandSpec... specs) throws IOException {
- Assert.notNull(config, "config");
- Assert.notNull(config.directory, "output directory");
- Assert.notNull(config.verbosity, "verbosity array");
-
- if (config.templatesDirectory != null && config.templatesDirectory.equals(config.directory)) {
- System.err.println("gen-manpage: Error: output directory must differ from the templates directory.");
- System.err.println("Try 'gen-manpage --help' for more information.");
- return CommandLine.ExitCode.USAGE;
- }
-
- traceAllSpecs(specs, config);
-
- for (CommandSpec spec : specs) {
- int result = generateSingleManPage(config, spec);
- if (result != CommandLine.ExitCode.OK) {
- return result;
- }
-
- Set done = new HashSet();
-
- // recursively create man pages for subcommands
- for (CommandLine sub : spec.subcommands().values()) {
- CommandSpec subSpec = sub.getCommandSpec();
- if (done.contains(subSpec) || subSpec.usageMessage().hidden()) {
- continue;
- }
- done.add(subSpec);
- result = generateManPage(config, subSpec);
- if (result != CommandLine.ExitCode.OK) {
- return result;
- }
- }
- }
-
- return CommandLine.ExitCode.OK;
- }
-
- private static int generateNavPage(Config config, CommandSpec spec) throws IOException {
-
- // generate navigation
-
-
- if (!mkdirs(config, new File(config.directory, "partials"))) {
- return CommandLine.ExitCode.SOFTWARE;
- }
- File manpage = new File(config.directory, "partials/" + makeNavFileName(spec));
- config.verbose("Generating navigation index %s%n", manpage);
-
- OutputStreamWriter writer = null;
- PrintWriter pw = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(manpage), "UTF-8");
- pw = new PrintWriter(writer);
- spec.commandLine().setColorScheme(PLAIN_SCHEME);
-
- Set done = new HashSet();
-
- generateNavForHelp(config, "", pw, spec.commandLine().getHelp());
- generateSingleNav(config, spec, "", pw);
-
- } finally {
- Util.closeSilently(pw);
- Util.closeSilently(writer);
+ if (className == null) {
+ System.err.println("Usage: genadoc [-d outdir] [--force] ");
+ System.exit(2);
}
- return CommandLine.ExitCode.OK;
- }
- private static void generateSingleNav(Config config, CommandSpec spec, String indent, PrintWriter pw) {
- for (CommandLine.Help subHelp : spec.commandLine().getHelp().subcommands().values()) {
- generateNavForHelp(config, "*" + indent, pw, subHelp);
- generateSingleNav(config,subHelp.commandSpec(), "*" + indent, pw);
- }
- }
+ @SuppressWarnings("unchecked")
+ Class extends Command> cmdClass = (Class extends Command>) Class.forName(className);
- private static void generateNavForHelp(Config config, String indent, PrintWriter pw, CommandLine.Help subHelp) {
- pw.println();
- Text namesText = subHelp.commandNamesText(", ");
- String names = namesText.toString();
- String xrefname = config.componentRoot + makeFileName(subHelp.commandSpec());
- pw.printf("%s* xref:%s[%s]", indent, xrefname, names);
- }
-
- private static void traceAllSpecs(CommandSpec[] specs, Config config) {
- List all = new ArrayList();
- for (CommandSpec spec : specs) {
- Object obj = spec.userObject();
- if (obj == null) {
- all.add(spec.name() + " (no user object)");
- } else if (obj instanceof Method) {
- all.add(spec.name() + " (" + ((Method) obj).toGenericString() + ")");
- } else {
- all.add(obj.getClass().getName());
- }
- }
- config.verbose("Generating man pages for %s and all subcommands%n", all);
- }
+ AeshCommandContainerBuilder> builder = new AeshCommandContainerBuilder<>();
+ CommandContainer> container = builder.create(cmdClass);
+ CommandLineParser> rootParser = container.getParser();
- private static int generateSingleManPage(Config config, CommandSpec spec) throws IOException {
- if (!mkdirs(config, new File(config.directory, "pages"))) {
- return CommandLine.ExitCode.SOFTWARE;
- }
- File manpage = new File(config.directory, "pages/" + makeFileName(spec));
- config.verbose("Generating man page %s%n", manpage);
+ Path pagesDir = Paths.get(outDir, "pages");
+ Path partialsDir = Paths.get(outDir, "partials");
+ Files.createDirectories(pagesDir);
+ Files.createDirectories(partialsDir);
- generateSingleManPage(config, spec, manpage);
+ generateManPages(rootParser, pagesDir);
+ generateNav(rootParser, Paths.get(outDir, "nav.adoc"));
- return generateCustomizableTemplate(config, spec);
+ System.out.println("Documentation generated in " + outDir);
}
- private static boolean mkdirs(Config config, File directory) {
- if (directory != null && !directory.exists()) {
- config.verboseDetailed("Creating directory %s%n", directory);
+ static void generateManPages(CommandLineParser> parser, Path pagesDir) throws IOException {
+ String rootName = parser.getProcessedCommand().name();
+ generateSinglePage(parser, rootName, null, pagesDir);
- if (!directory.mkdirs()) {
- System.err.println("Unable to mkdirs for " + directory.getAbsolutePath());
- return false;
+ List> children = getAllChildParsers(parser);
+ if (children != null) {
+ for (CommandLineParser> child : children) {
+ String childQualified = rootName + "-" + child.getProcessedCommand().name();
+ generateSinglePage(child, childQualified, parser, pagesDir);
+ List> grandchildren = getAllChildParsers(child);
+ if (grandchildren != null) {
+ for (CommandLineParser> grandchild : grandchildren) {
+ String gcQualified = childQualified + "-" + grandchild.getProcessedCommand().name();
+ generateSinglePage(grandchild, gcQualified, child, pagesDir);
+ }
+ }
}
}
- return true;
}
- private static String makeFileName(CommandSpec spec) {
- return (spec.qualifiedName("-") + ".adoc").replaceAll("\\s", "_").replace("", "main_class");
- }
-
- private static String makeNavFileName(CommandSpec spec) {
- return ("nav-" + spec.qualifiedName("-") + ".adoc").replaceAll("\\s", "_").replace("",
- "main_class");
- }
-
- private static void generateSingleManPage(Config config, CommandSpec spec, File manpage) throws IOException {
- OutputStreamWriter writer = null;
- PrintWriter pw = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(manpage), "UTF-8");
- pw = new PrintWriter(writer);
- writeSingleManPage(config, pw, spec);
- } finally {
- Util.closeSilently(pw);
- Util.closeSilently(writer);
+ @SuppressWarnings("unchecked")
+ static List> getAllChildParsers(CommandLineParser> parser) {
+ if (!parser.isGroupCommand()) return null;
+ if (parser instanceof AeshCommandLineParser) {
+ AeshCommandLineParser> aeshParser = (AeshCommandLineParser>) parser;
+ return (List>) (List>) aeshParser.getAllChildParsers();
}
+ return null;
}
- private static int generateCustomizableTemplate(Config config, CommandSpec spec) throws IOException {
- if (config.templatesDirectory == null) {
- return CommandLine.ExitCode.OK;
- }
- if (!mkdirs(config, config.templatesDirectory)) {
- return CommandLine.ExitCode.SOFTWARE;
- }
-
- File templateFile = new File(config.templatesDirectory, makeFileName(spec));
- if (templateFile.exists()) {
- if (config.force) {
- config.verbose("Overwriting existing man page template file %s...%n", templateFile);
- } else {
- System.err.printf("gen-manpage: ERROR: cannot generate man page template file %s: it already exists. "
- + "Remove the --template-dir option or use --force to overwrite.%n", templateFile);
- System.err.println("Try 'gen-manpage --help' for more information.");
- return EXIT_CODE_TEMPLATE_EXISTS;
- }
- } else {
- config.verbose("Generating customizable man page template %s%n", templateFile);
- }
+ static void generateSinglePage(CommandLineParser> parser, String qualifiedName,
+ CommandLineParser> parent, Path pagesDir) throws IOException {
+ Path file = pagesDir.resolve(qualifiedName + ".adoc");
- FileWriter writer = null;
- PrintWriter pw = null;
- try {
- writer = new FileWriter(templateFile);
- pw = new PrintWriter(writer);
- writeCustomizableManPageTemplate(pw, config.directory, spec);
- } finally {
- Util.closeSilently(pw);
- Util.closeSilently(writer);
+ try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(
+ new FileOutputStream(file.toFile()), "UTF-8"))) {
+ writePage(pw, parser, parent, qualifiedName);
}
- return CommandLine.ExitCode.OK;
}
- static void writeCustomizableManPageTemplate(PrintWriter pw, File includeDir, CommandSpec spec) {
- pw.printf(":includedir: %s%n", includeDir.getAbsolutePath().replace('\\', '/'));
- pw.printf("//include::{includedir}/%s[tag=picocli-generated-full-manpage]%n", makeFileName(spec));
+ static void writePage(PrintWriter pw, CommandLineParser> parser, CommandLineParser> parent,
+ String qualifiedName) {
+ ProcessedCommand, ?> cmd = parser.getProcessedCommand();
+ String name = cmd.name();
+ String description = cmd.description() != null ? cmd.description() : "";
+ String appName = parent != null ? parent.getProcessedCommand().name() : name;
- List tags = Arrays.asList("header", "name", "synopsis", "description", "options", "arguments",
- "commands", "exit-status", "footer");
- for (String tag : tags) {
- pw.println(); // ensure that the include directives are separated with a newline
- pw.printf("include::{includedir}/%s[tag=picocli-generated-man-section-%s]%n", makeFileName(spec), tag);
- }
- }
+ pw.println("// This is a generated documentation file based on aesh");
+ pw.println("// To change it update the aesh code or the generator");
+ pw.println("// tag::picocli-generated-full-manpage[]");
- public static void writeSingleManPage(Config config, PrintWriter pw, CommandSpec spec) {
- spec.commandLine().setColorScheme(COLOR_SCHEME);
- pw.println("// This is a generated documentation file based on picocli");
- pw.println("// To change it update the picocli code or the genrator");
-
- pw.printf("// tag::picocli-generated-full-manpage[]%n");
- genHeader(pw, spec);
- genOptions(pw, spec);
- genPositionalArgs(pw, spec);
- genCommands(config, pw, spec);
- genExitStatus(pw, spec);
- genFooter(pw, spec);
- pw.printf("// end::picocli-generated-full-manpage[]%n");
- }
-
- static void genHeader(PrintWriter pw, CommandSpec spec) {
- pw.printf("// tag::picocli-generated-man-section-header[]%n");
- pw.printf(":doctype: manpage%n");
- // pw.printf(":authors: %s%n", spec.userObject()); // author
- //pw.printf(":revnumber: %s%n", versionString(spec)); // version not included to avoid unnecessary generation
- pw.printf(":manmanual: %s%n", manualTitle(spec));
- //pw.printf(":mansource: %s%n", versionString(spec)); // spec.qualifiedName("-").toUpperCase()
- pw.printf(":man-linkstyle: pass:[blue R < >]%n");
- pw.printf("= %s(1)%n", spec.qualifiedName("-")); // command name (lower case)
+ // Header
+ pw.println("// tag::picocli-generated-man-section-header[]");
+ pw.println(":doctype: manpage");
+ pw.println(format(":manmanual: %s Manual", appName));
+ pw.println(":man-linkstyle: pass:[blue R < >]");
+ pw.println(format("= %s(1)", qualifiedName));
pw.println();
- pw.printf("// end::picocli-generated-man-section-header[]%n");
+ pw.println("// end::picocli-generated-man-section-header[]");
pw.println();
- pw.printf("// tag::picocli-generated-man-section-name[]%n");
- pw.printf("== Name%n%n");
- pw.printf("%s - %s%n", spec.qualifiedName("-"), headerDescriptionString(spec)); // name and description
+ // Name
+ pw.println("// tag::picocli-generated-man-section-name[]");
+ pw.println("== Name");
+ pw.println();
+ String displayName = parent != null ? parent.getProcessedCommand().name() + "-" + name : name;
+ pw.println(format("%s - %s", displayName, description));
pw.println();
- pw.printf("// end::picocli-generated-man-section-name[]%n");
+ pw.println("// end::picocli-generated-man-section-name[]");
pw.println();
- pw.printf("// tag::picocli-generated-man-section-synopsis[]%n");
- pw.printf("== Synopsis%n%n");
- pw.printf("%s", spec.commandLine().getHelp().synopsis(0));
+ // Synopsis
+ pw.println("// tag::picocli-generated-man-section-synopsis[]");
+ pw.println("== Synopsis");
pw.println();
- pw.printf("// end::picocli-generated-man-section-synopsis[]%n");
+ pw.print(generateSynopsis(parser, parent));
+ pw.println();
+ pw.println("// end::picocli-generated-man-section-synopsis[]");
pw.println();
- pw.printf("// tag::picocli-generated-man-section-description[]%n");
- pw.printf("== Description%n%n");
- pw.printf("%s%n",
- format(COLOR_SCHEME.text(join("%n", (Object[]) spec.usageMessage().description())).toString())); // description
+ // Description
+ pw.println("// tag::picocli-generated-man-section-description[]");
+ pw.println("== Description");
pw.println();
- pw.printf("// end::picocli-generated-man-section-description[]%n");
+ pw.println(description);
+ pw.println();
+ pw.println("// end::picocli-generated-man-section-description[]");
pw.println();
- }
-
- private static String versionString(CommandSpec spec) {
- return spec.version().length == 0 ? "" : spec.version()[0].replaceAll(":", " ");
- }
-
- private static String manualTitle(CommandSpec spec) {
- CommandSpec parent = spec;
- while (parent.parent() != null) {
- parent = parent.parent();
- }
- String name = parent.name();
- return name + " Manual";
- }
-
- private static String headerDescriptionString(CommandSpec spec) {
- String result = null;
- String[] headerDescription = spec.usageMessage().header();
- if (headerDescription == null || headerDescription.length == 0 || headerDescription[0] == null
- || headerDescription[0].length() == 0) {
- // if the command does not have a header, use only the first line from the
- // description:
- // the other lines will be shown in the DESCRIPTION section of the man page
- result = firstElement(spec.usageMessage().description());
- } else {
- // if the command header has multiple lines, we display all of them in the NAME
- // section
- result = join("%n", (Object[]) headerDescription);
- }
- return format(COLOR_SCHEME.text(result).toString()); // convert any embedded %n strings to newlines
- }
-
- static void genOptions(PrintWriter pw, CommandSpec spec) {
- List options = new ArrayList(spec.options()); // options are stored in order of
- // declaration
-
- // remove hidden options
- for (Iterator iter = options.iterator(); iter.hasNext();) {
- if (iter.next().hidden()) {
- iter.remove();
- }
- }
-
- IOptionRenderer optionRenderer = spec.commandLine().getHelp().createDefaultOptionRenderer();
- IParamLabelRenderer paramLabelRenderer = spec.commandLine().getHelp().createDefaultParamLabelRenderer();
- IParameterRenderer parameterRenderer = spec.commandLine().getHelp().createDefaultParameterRenderer();
-
- List groups = optionListGroups(spec);
- for (ArgGroupSpec group : groups) {
- options.removeAll(group.options());
- }
- if (options.isEmpty() && !spec.usageMessage().showEndOfOptionsDelimiterInUsageHelp()) {
- pw.printf("// tag::picocli-generated-man-section-options[]%n");
- pw.printf("// end::picocli-generated-man-section-options[]%n");
+ // Options
+ pw.println("// tag::picocli-generated-man-section-options[]");
+ List options = cmd.getOptions();
+ if (options != null && !options.isEmpty()) {
+ pw.println("== Options");
pw.println();
- return;
- }
- pw.printf("// tag::picocli-generated-man-section-options[]%n");
- pw.printf("== Options%n");
-
- Comparator optionSort = spec.usageMessage().sortOptions()
- ? new SortByShortestOptionNameAlphabetically()
- : createOrderComparatorIfNecessary(spec.options());
- if (optionSort != null) {
- Collections.sort(options, optionSort); // default: sort options ABC
- }
- for (OptionSpec option : options) {
- writeOption(pw, optionRenderer, paramLabelRenderer, option);
- }
-
- if (spec.usageMessage().showEndOfOptionsDelimiterInUsageHelp()) {
- CommandLine cmd = new CommandLine(spec).setColorScheme(COLOR_SCHEME);
- CommandLine.Help help = cmd.getHelp();
- writeEndOfOptions(pw, optionRenderer, paramLabelRenderer, help.END_OF_OPTIONS_OPTION);
+ for (ProcessedOption opt : options) {
+ if (isHidden(opt)) continue;
+ writeOption(pw, opt);
+ }
}
+ pw.println("// end::picocli-generated-man-section-options[]");
+ pw.println();
- // now create a custom option section for each arg group that has a heading
- Collections.sort(groups, new SortByOrder());
- for (ArgGroupSpec group : groups) {
+ // Arguments
+ pw.println("// tag::picocli-generated-man-section-arguments[]");
+ ProcessedOption argument = cmd.getArgument();
+ ProcessedOption arguments = cmd.getArguments();
+ if (argument != null || arguments != null) {
+ pw.println("== Arguments");
pw.println();
- String heading = makeHeading(group.heading(), "Options Group");
- pw.printf("== %s%n", COLOR_SCHEME.text(heading));
-
- for (PositionalParamSpec positional : group.positionalParameters()) {
- if (!positional.hidden()) {
- writePositional(pw, positional, parameterRenderer, paramLabelRenderer);
- }
+ if (argument != null) {
+ writeArgument(pw, argument);
}
- List groupOptions = new ArrayList(group.options());
- if (optionSort != null) {
- Collections.sort(groupOptions, optionSort);
- }
- for (OptionSpec option : groupOptions) {
- writeOption(pw, optionRenderer, paramLabelRenderer, option);
+ if (arguments != null) {
+ writeArgument(pw, arguments);
}
}
+ pw.println("// end::picocli-generated-man-section-arguments[]");
pw.println();
- pw.printf("// end::picocli-generated-man-section-options[]%n");
- pw.println();
- }
-
- /**
- * Returns the list of {@code ArgGroupSpec}s with a non-{@code null} heading.
- */
- private static List optionListGroups(CommandSpec commandSpec) {
- List result = new ArrayList();
- optionListGroups(commandSpec.argGroups(), result);
- return result;
- }
- private static void optionListGroups(List groups, List result) {
- for (ArgGroupSpec group : groups) {
- optionListGroups(group.subgroups(), result);
- if (group.heading() != null) {
- result.add(group);
+ // Subcommands
+ pw.println("// tag::picocli-generated-man-section-commands[]");
+ List> children = getAllChildParsers(parser);
+ if (children != null && !children.isEmpty()) {
+ pw.println("== Commands");
+ pw.println();
+ for (CommandLineParser> child : children) {
+ ProcessedCommand, ?> childCmd = child.getProcessedCommand();
+ String childQualified = qualifiedName + "-" + childCmd.name();
+ pw.println(format("xref:%s%s.adoc[*%s*]::", componentRoot, childQualified, childCmd.name()));
+ pw.println(format(" %s", childCmd.description() != null ? childCmd.description() : ""));
+ pw.println();
}
}
- }
-
- private static void writeOption(PrintWriter pw, IOptionRenderer optionRenderer,
- IParamLabelRenderer paramLabelRenderer, OptionSpec option) {
+ pw.println("// end::picocli-generated-man-section-commands[]");
pw.println();
- Text[][] rows = optionRenderer.render(option, paramLabelRenderer, COLOR_SCHEME);
- pw.printf("%s::%n", join(", ", rows[0][1], rows[0][3]));
- pw.printf(" %s%n", rows[0][4]);
- for (int i = 1; i < rows.length; i++) {
- pw.printf("+%n%s%n", rows[i][4]);
- }
- }
- private static void writePositional(PrintWriter pw, PositionalParamSpec positional,
- IParameterRenderer parameterRenderer, IParamLabelRenderer paramLabelRenderer) {
+ // Exit status (empty for now)
+ pw.println("// tag::picocli-generated-man-section-exit-status[]");
+ pw.println("// end::picocli-generated-man-section-exit-status[]");
pw.println();
- Text[][] rows = parameterRenderer.render(positional, paramLabelRenderer, COLOR_SCHEME);
- pw.printf("%s::%n", join(", ", rows[0][1], rows[0][3]));
- pw.printf(" %s%n", rows[0][4]);
- for (int i = 1; i < rows.length; i++) {
- pw.printf("+%n%s%n", rows[i][4]);
- }
- }
- /** Write the end of options. */
- private static void writeEndOfOptions(PrintWriter pw, IOptionRenderer optionRenderer,
- IParamLabelRenderer paramLabelRenderer, OptionSpec option) {
+ // Footer (empty for now)
+ pw.println("// tag::picocli-generated-man-section-footer[]");
+ pw.println("// end::picocli-generated-man-section-footer[]");
pw.println();
- Text[][] rows = optionRenderer.render(option, paramLabelRenderer, COLOR_SCHEME);
- pw.printf("%s::%n", join("", rows[0][1], rows[0][3]));
- String description = String.valueOf(rows[0][4]);
- // ignore "${picocli.endofoptions.description:-" and "}"
- pw.printf(" %s%n", description.substring(36, description.length() - 1));
+
+ pw.println("// end::picocli-generated-full-manpage[]");
}
- static void genPositionalArgs(PrintWriter pw, CommandSpec spec) {
- List positionals = new ArrayList(spec.positionalParameters());
- // remove hidden params
- for (Iterator iter = positionals.iterator(); iter.hasNext();) {
- if (iter.next().hidden()) {
- iter.remove();
+ static String generateSynopsis(CommandLineParser> parser, CommandLineParser> parent) {
+ ProcessedCommand, ?> cmd = parser.getProcessedCommand();
+ StringBuilder sb = new StringBuilder();
+ if (parent != null) {
+ sb.append(format("*%s %s*", parent.getProcessedCommand().name(), cmd.name()));
+ } else {
+ sb.append(format("*%s*", cmd.name()));
+ }
+
+ List options = cmd.getOptions();
+ if (options != null) {
+ for (ProcessedOption opt : options) {
+ if (isHidden(opt)) continue;
+ sb.append(" ");
+ if (!opt.isRequired()) sb.append("[");
+ if (opt.shortName() != null && !opt.shortName().isEmpty()) {
+ sb.append(format("*-%s*", opt.shortName()));
+ } else {
+ sb.append(format("*--%s*", opt.name()));
+ }
+ if (opt.hasValue() && !isBooleanFlag(opt)) {
+ sb.append(format("=_<%s>_", opt.getArgument() != null ? opt.getArgument() : opt.name()));
+ }
+ if (!opt.isRequired()) sb.append("]");
}
}
- // positional parameters that are part of a group
- // are shown in the custom option section for that group
- List groups = optionListGroups(spec);
- for (ArgGroupSpec group : groups) {
- positionals.removeAll(group.positionalParameters());
- }
- if (positionals.isEmpty() && !spec.usageMessage().showAtFileInUsageHelp()) {
- pw.printf("// tag::picocli-generated-man-section-arguments[]%n");
- pw.printf("// end::picocli-generated-man-section-arguments[]%n");
- pw.println();
- return;
+ ProcessedOption argument = cmd.getArgument();
+ if (argument != null) {
+ sb.append(format(" [_<%s>_]", argumentLabel(argument)));
}
- pw.printf("// tag::picocli-generated-man-section-arguments[]%n");
- pw.printf("== Arguments%n");
-
- IParameterRenderer parameterRenderer = spec.commandLine().getHelp().createDefaultParameterRenderer();
- IParamLabelRenderer paramLabelRenderer = spec.commandLine().getHelp().createDefaultParamLabelRenderer();
-
- if (spec.usageMessage().showAtFileInUsageHelp()) {
- CommandLine cmd = new CommandLine(spec).setColorScheme(COLOR_SCHEME);
- CommandLine.Help help = cmd.getHelp();
- writePositional(pw, help.AT_FILE_POSITIONAL_PARAM, parameterRenderer, paramLabelRenderer);
+ ProcessedOption arguments = cmd.getArguments();
+ if (arguments != null) {
+ sb.append(format(" [_<%s>_...]", argumentLabel(arguments)));
}
- for (PositionalParamSpec positional : positionals) {
- writePositional(pw, positional, parameterRenderer, paramLabelRenderer);
- }
- pw.println();
- pw.printf("// end::picocli-generated-man-section-arguments[]%n");
- pw.println();
+ sb.append("\n");
+ return sb.toString();
}
- static void genCommands(Config config, PrintWriter pw, CommandSpec spec) {
-
- // remove hidden subcommands before tags are added
- Map subCommands = new LinkedHashMap(spec.subcommands());
- for (Iterator> iter = subCommands.entrySet().iterator(); iter.hasNext();) {
- if (iter.next().getValue().getCommandSpec().usageMessage().hidden()) {
- iter.remove();
+ static void writeOption(PrintWriter pw, ProcessedOption opt) {
+ StringBuilder names = new StringBuilder();
+ if (opt.shortName() != null && !opt.shortName().isEmpty()) {
+ names.append(format("*-%s*", opt.shortName()));
+ if (opt.name() != null && !opt.name().isEmpty()) {
+ names.append(format(", *--%s*", opt.name()));
+ }
+ } else if (opt.name() != null && !opt.name().isEmpty()) {
+ if (opt.isNegatable()) {
+ names.append(format("*--[no-]%s*", opt.name()));
+ } else {
+ names.append(format("*--%s*", opt.name()));
}
}
- if (spec.subcommands().isEmpty()) {
- pw.printf("// tag::picocli-generated-man-section-commands[]%n");
- pw.printf("// end::picocli-generated-man-section-commands[]%n");
- pw.println();
- return;
- }
- pw.printf("// tag::picocli-generated-man-section-commands[]%n");
- pw.printf("== Commands%n");
-
- for (CommandLine.Help subHelp : spec.commandLine().getHelp().subcommands().values()) {
- pw.println();
-
- Text namesText = subHelp.commandNamesText(", ");
- String names = namesText.toString();
- String xrefname = config.componentRoot + makeFileName(subHelp.commandSpec());
- pw.printf("xref:%s[%s]::%n", xrefname, names);
-
- CommandLine.Model.UsageMessageSpec usage = subHelp.commandSpec().usageMessage();
- String header = !empty(usage.header()) ? usage.header()[0]
- : (!empty(usage.description()) ? usage.description()[0] : "");
- Text[] lines = COLOR_SCHEME.text(format(header)).splitLines();
-
- pw.printf(" %s%n", lines[0].toString());
- for (int i = 1; i < lines.length; i++) {
- pw.printf("+%n%s%n", lines[i].toString());
+ // Show aliases (e.g. --ea for --enableassertions)
+ List aliases = opt.getAliases();
+ if (aliases != null) {
+ for (String alias : aliases) {
+ names.append(format(", *--%s*", alias));
}
}
- pw.println();
- pw.printf("// end::picocli-generated-man-section-commands[]%n");
- pw.println();
- }
- static void genExitStatus(PrintWriter pw, CommandSpec spec) {
- if (spec.usageMessage().exitCodeList().isEmpty()) {
- pw.printf("// tag::picocli-generated-man-section-exit-status[]%n");
- pw.printf("// end::picocli-generated-man-section-exit-status[]%n");
- pw.println();
- return;
+ if (opt.hasValue() && !isBooleanFlag(opt)) {
+ names.append(format("=_<%s>_", opt.getArgument() != null ? opt.getArgument() : opt.name()));
}
- String heading = makeHeading(spec.usageMessage().exitCodeListHeading(), "Exit status");
- pw.printf("// tag::picocli-generated-man-section-exit-status[]%n");
- // pw.printf("== Exit status%n");
- pw.printf("== %s%n", COLOR_SCHEME.text(heading));
- for (Map.Entry entry : spec.usageMessage().exitCodeList().entrySet()) {
- pw.println();
- pw.printf("*%s*::%n", COLOR_SCHEME.text(entry.getKey().trim()));
- pw.printf(" %s%n", COLOR_SCHEME.text(entry.getValue()));
- }
- pw.println();
- pw.printf("// end::picocli-generated-man-section-exit-status[]%n");
+ pw.println(format("%s::", names));
+ String desc = opt.description() != null ? opt.description() : "";
+ pw.println(format(" %s", desc));
pw.println();
}
- static void genFooter(PrintWriter pw, CommandSpec spec) {
- if (spec.usageMessage().footerHeading().length() == 0 || spec.usageMessage().footer().length == 0) {
- pw.printf("// tag::picocli-generated-man-section-footer[]%n");
- pw.printf("// end::picocli-generated-man-section-footer[]%n");
- pw.println();
- return;
- }
- String heading = makeHeading(spec.usageMessage().footerHeading(), "Footer");
- pw.printf("// tag::picocli-generated-man-section-footer[]%n");
- pw.printf("== %s%n", COLOR_SCHEME.text(heading));
- pw.println();
-
- boolean hardbreaks = true;
- for (String line : spec.usageMessage().footer()) {
-
- if (hardbreaks) {
- pw.println("[%hardbreaks]"); // preserve line breaks
- hardbreaks = false;
- }
- String renderedLine = COLOR_SCHEME.text(format(line)).toString();
-
- // Lines that start with "# " may be intended as shell comments,
- // but are rendered as AsciiDoc headers (equivalent to "= ...").
- // We use a passthrough to prevent substitution. (TODO Should this be
- // customizable?)
- // See https://asciidoctor.org/docs/user-manual/#passthroughs
- if (renderedLine.startsWith("# ")) {
- renderedLine = "pass:c[# ]" + renderedLine.substring(2);
- }
- pw.printf("%s%n", renderedLine);
- if (line.trim().length() == 0) {
- hardbreaks = true;
- }
- }
- pw.println();
- pw.printf("// end::picocli-generated-man-section-footer[]%n");
+ static void writeArgument(PrintWriter pw, ProcessedOption arg) {
+ String label = argumentLabel(arg);
+ pw.println(format("_<%s>_::", label));
+ String desc = arg.description() != null ? arg.description() : "";
+ pw.println(format(" %s", desc));
pw.println();
}
- private static String makeHeading(String heading, String defaultIfEmpty) {
- if (heading.endsWith("%n")) {
- heading = heading.substring(0, heading.length() - 2);
+ static String argumentLabel(ProcessedOption arg) {
+ if (arg.getParamLabel() != null && !arg.getParamLabel().isEmpty()) {
+ return arg.getParamLabel();
}
- heading = heading.trim().length() == 0 ? defaultIfEmpty : heading.replaceAll("%n", " ");
- return heading;
- }
-
- private static Comparator createOrderComparatorIfNecessary(List options) {
- for (OptionSpec option : options) {
- if (option.order() != -1/* OptionSpec.DEFAULT_ORDER */) {
- return new SortByOrder();
- }
+ if (arg.name() != null && !arg.name().isEmpty()) {
+ return arg.name();
}
- return null;
+ return "arg";
}
- static class SortByOrder implements Comparator {
- public int compare(T o1, T o2) {
- return Integer.signum(o1.order() - o2.order());
+ static boolean isBooleanFlag(ProcessedOption opt) {
+ if ("help".equals(opt.name())) {
+ return true;
}
+ Class> t = opt.type();
+ return t.equals(Boolean.class) || t.equals(boolean.class);
}
- /** Sorts short strings before longer strings. */
- static class ShortestFirst implements Comparator {
- public int compare(String o1, String o2) {
- return o1.length() - o2.length();
- }
-
- /** Sorts the specified array of Strings shortest-first and returns it. */
- public static String[] sort(String[] names) {
- Arrays.sort(names, new ShortestFirst());
- return names;
- }
-
- /** Sorts the specified array of Strings longest-first and returns it. */
- public static String[] longestFirst(String[] names) {
- Arrays.sort(names, Collections.reverseOrder(new ShortestFirst()));
- return names;
- }
+ static boolean isHidden(ProcessedOption opt) {
+ return opt.getVisibility() == org.aesh.command.option.OptionVisibility.HIDDEN;
}
- /**
- * Sorts {@code OptionSpec} instances by their name in case-insensitive
- * alphabetic order. If an option has multiple names, the shortest name is used
- * for the sorting. Help options follow non-help options.
- */
- static class SortByShortestOptionNameAlphabetically implements Comparator {
- @SuppressWarnings("deprecation")
- public int compare(OptionSpec o1, OptionSpec o2) {
- if (o1 == null) {
- return 1;
- } else if (o2 == null) {
- return -1;
- } // options before params
- String[] names1 = ShortestFirst.sort(o1.names());
- String[] names2 = ShortestFirst.sort(o2.names());
- String s1 = stripPrefix(names1[0]);
- String s2 = stripPrefix(names2[0]);
- int result = s1.toUpperCase().compareTo(s2.toUpperCase()); // case insensitive sort
- result = result == 0 ? -s1.compareTo(s2) : result; // lower case before upper case
- return o1.help() == o2.help() ? result : o2.help() ? -1 : 1; // help options come last
- }
+ static List sorted(List options) {
+ List sorted = new ArrayList<>(options);
+ sorted.sort((a, b) -> {
+ String na = a.name() != null ? a.name() : (a.shortName() != null ? a.shortName() : "");
+ String nb = b.name() != null ? b.name() : (b.shortName() != null ? b.shortName() : "");
+ return na.compareToIgnoreCase(nb);
+ });
+ return sorted;
}
- private static String join(String sep, Object... lines) {
- StringBuilder sb = new StringBuilder();
- for (Object line : lines) {
- if (sb.length() > 0) {
- sb.append(sep);
- }
- sb.append(line);
+ static String qualifiedName(CommandLineParser> parser, CommandLineParser> parent) {
+ String name = parser.getProcessedCommand().name();
+ if (parent != null) {
+ String parentName = parent.getProcessedCommand().name();
+ return parentName + "-" + name;
}
- return sb.toString();
+ return name;
}
- private static String firstElement(String[] elements) {
- if (elements == null || elements.length == 0) {
- return "";
- }
- return elements[0];
- }
+ static void generateNav(CommandLineParser> rootParser, Path navFile) throws IOException {
+ try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(
+ new FileOutputStream(navFile.toFile()), "UTF-8"))) {
+ String rootName = rootParser.getProcessedCommand().name();
+ pw.println(format("* xref:%s%s.adoc[%s]", componentRoot, rootName, rootName));
- private static boolean empty(Object[] array) {
- return array == null || array.length == 0;
- }
+ List> children = getAllChildParsers(rootParser);
+ if (children != null) {
+ for (CommandLineParser> child : children) {
+ String childName = child.getProcessedCommand().name();
+ String qualified = rootName + "-" + childName;
+ pw.println(format("** xref:%s%s.adoc[%s]", componentRoot, qualified, childName));
- static String stripPrefix(String prefixed) {
- for (int i = 0; i < prefixed.length(); i++) {
- if (Character.isJavaIdentifierPart(prefixed.charAt(i))) {
- return prefixed.substring(i);
+ List> grandchildren = getAllChildParsers(child);
+ if (grandchildren != null) {
+ for (CommandLineParser> grandchild : grandchildren) {
+ String gcName = grandchild.getProcessedCommand().name();
+ String gcQualified = qualified + "-" + gcName;
+ pw.println(format("*** xref:%s%s.adoc[%s]", componentRoot, gcQualified, gcName));
+ }
+ }
+ }
}
}
- return prefixed;
}
-}
\ No newline at end of file
+}
diff --git a/docs/modules/cli/nav.adoc b/docs/modules/cli/nav.adoc
index fac667c48..85b71574b 100644
--- a/docs/modules/cli/nav.adoc
+++ b/docs/modules/cli/nav.adoc
@@ -1,5 +1,63 @@
-* CLI Reference
-+
---
-include::partial$nav-jbang.adoc[]
---
\ No newline at end of file
+* xref:jbang:cli:jbang.adoc[jbang]
+** xref:jbang:cli:jbang-run.adoc[run]
+** xref:jbang:cli:jbang-build.adoc[build]
+** xref:jbang:cli:jbang-edit.adoc[edit]
+** xref:jbang:cli:jbang-init.adoc[init]
+** xref:jbang:cli:jbang-alias.adoc[alias]
+*** xref:jbang:cli:jbang-alias-add.adoc[add]
+*** xref:jbang:cli:jbang-alias-list.adoc[list]
+*** xref:jbang:cli:jbang-alias-remove.adoc[remove]
+** xref:jbang:cli:jbang-template.adoc[template]
+*** xref:jbang:cli:jbang-template-add.adoc[add]
+*** xref:jbang:cli:jbang-template-list.adoc[list]
+*** xref:jbang:cli:jbang-template-remove.adoc[remove]
+** xref:jbang:cli:jbang-catalog.adoc[catalog]
+*** xref:jbang:cli:jbang-catalog-add.adoc[add]
+*** xref:jbang:cli:jbang-catalog-update.adoc[update]
+*** xref:jbang:cli:jbang-catalog-list.adoc[list]
+*** xref:jbang:cli:jbang-catalog-remove.adoc[remove]
+** xref:jbang:cli:jbang-trust.adoc[trust]
+*** xref:jbang:cli:jbang-trust-add.adoc[add]
+*** xref:jbang:cli:jbang-trust-list.adoc[list]
+*** xref:jbang:cli:jbang-trust-remove.adoc[remove]
+** xref:jbang:cli:jbang-cache.adoc[cache]
+*** xref:jbang:cli:jbang-cache-clear.adoc[clear]
+** xref:jbang:cli:jbang-completion.adoc[completion]
+** xref:jbang:cli:jbang-jdk.adoc[jdk]
+*** xref:jbang:cli:jbang-jdk-install.adoc[install]
+*** xref:jbang:cli:jbang-jdk-list.adoc[list]
+*** xref:jbang:cli:jbang-jdk-uninstall.adoc[uninstall]
+*** xref:jbang:cli:jbang-jdk-home.adoc[home]
+*** xref:jbang:cli:jbang-jdk-java-env.adoc[java-env]
+*** xref:jbang:cli:jbang-jdk-exec.adoc[exec]
+*** xref:jbang:cli:jbang-jdk-default.adoc[default]
+** xref:jbang:cli:jbang-version.adoc[version]
+** xref:jbang:cli:jbang-wrapper.adoc[wrapper]
+*** xref:jbang:cli:jbang-wrapper-install.adoc[install]
+** xref:jbang:cli:jbang-info.adoc[info]
+*** xref:jbang:cli:jbang-info-tools.adoc[tools]
+*** xref:jbang:cli:jbang-info-classpath.adoc[classpath]
+*** xref:jbang:cli:jbang-info-jar.adoc[jar]
+*** xref:jbang:cli:jbang-info-docs.adoc[docs]
+** xref:jbang:cli:jbang-app.adoc[app]
+*** xref:jbang:cli:jbang-app-install.adoc[install]
+*** xref:jbang:cli:jbang-app-list.adoc[list]
+*** xref:jbang:cli:jbang-app-uninstall.adoc[uninstall]
+*** xref:jbang:cli:jbang-app-setup.adoc[setup]
+** xref:jbang:cli:jbang-export.adoc[export]
+*** xref:jbang:cli:jbang-export-portable.adoc[portable]
+*** xref:jbang:cli:jbang-export-local.adoc[local]
+*** xref:jbang:cli:jbang-export-mavenrepo.adoc[mavenrepo]
+*** xref:jbang:cli:jbang-export-native.adoc[native]
+*** xref:jbang:cli:jbang-export-fatjar.adoc[fatjar]
+*** xref:jbang:cli:jbang-export-jlink.adoc[jlink]
+*** xref:jbang:cli:jbang-export-gradle.adoc[gradle]
+*** xref:jbang:cli:jbang-export-maven.adoc[maven]
+** xref:jbang:cli:jbang-config.adoc[config]
+*** xref:jbang:cli:jbang-config-get.adoc[get]
+*** xref:jbang:cli:jbang-config-set.adoc[set]
+*** xref:jbang:cli:jbang-config-unset.adoc[unset]
+*** xref:jbang:cli:jbang-config-list.adoc[list]
+** xref:jbang:cli:jbang-deps.adoc[deps]
+*** xref:jbang:cli:jbang-deps-search.adoc[search]
+*** xref:jbang:cli:jbang-deps-add.adoc[add]
diff --git a/docs/modules/cli/pages/jbang-alias-add.adoc b/docs/modules/cli/pages/jbang-alias-add.adoc
index c3e149785..74dfb50a3 100644
--- a/docs/modules/cli/pages/jbang-alias-add.adoc
+++ b/docs/modules/cli/pages/jbang-alias-add.adoc
@@ -1,9 +1,9 @@
-// This is a generated documentation file based on picocli
-// To change it update the picocli code or the genrator
+// This is a generated documentation file based on aesh
+// To change it update the aesh code or the generator
// tag::picocli-generated-full-manpage[]
// tag::picocli-generated-man-section-header[]
:doctype: manpage
-:manmanual: jbang Manual
+:manmanual: alias Manual
:man-linkstyle: pass:[blue R < >]
= jbang-alias-add(1)
@@ -12,27 +12,14 @@
// tag::picocli-generated-man-section-name[]
== Name
-jbang-alias-add - Add alias for script reference.
+alias-add - Add alias for script reference.
// end::picocli-generated-man-section-name[]
// tag::picocli-generated-man-section-synopsis[]
== Synopsis
-*jbang alias add* *-o* [*-ghin*] [*--[no-]cds*] [*--ea*] [*--enable-preview*] [*--esa*]
- [*--force*] *--fresh* [*--insecure*] [*--[no-]integrations*] [*--itr*]
- [*--jsh*] *--quiet* *--verbose* [*--jfr*[=__]]
- [*--module*[=__]] [*-d*[=__]]...
- [*--catalog*=__] [*--config*=__]
- [*--description*=__] [*-f*=__]
- [*-j*=__] [*-m*=__] [*--name*=__] [*-T*=__]
- [*-C*=__]... [*--cp*=__]...
- [*-D*=__]... [*--deps*=__]...
- [*--docs*=__]... [*--files*=__]...
- [*--javaagent*=__]...
- [*--manifest*=__]... [*-N*=__]...
- [*-R*=__]... [*--repos*=__]...
- [*-s*=__]... [__] [_params_...]
+*alias add* [*-h*] [*-s*=__] [*--files*=__] [*-T*=__] [*--jsh*] [*--catalog*=__] [*-j*=__] [*-m*=__] [*--module*=__] [*-C*=__] [*--manifest*=__] [*--integrations*] [*-D*=__] [*--deps*=__] [*--repos*=__] [*--cp*=__] [*--ignore-transitive-repositories*] [*-n*] [*-N*=__] [*-R*=__] [*--jfr*=__] [*-d*=__] [*--enableassertions*] [*--enablesystemassertions*] [*--javaagent*=__] [*--cds*] [*-i*] [*-g*] [*-f*=__] [*--description*=__] [*--name*=__] [*--force*] [*--enable-preview*] [*--docs*=__] [*--config*=__] [*--insecure*] [*--verbose*] [*--quiet*] [*-o*] [*--fresh*] [*--preview*] [*-x*] [__] [__...]
// end::picocli-generated-man-section-synopsis[]
@@ -46,135 +33,141 @@ Add alias for script reference.
// tag::picocli-generated-man-section-options[]
== Options
-*-C*, *--compile-option*=__::
- Options to pass to the compiler
+*-h*, *--help*::
+ Display help (use --help=all for all options)
+
+*-s*, *--sources*=__::
+ Add additional sources.
+
+*--files*=__::
+ Add additional files.
+
+*-T*, *--source-type*=__::
+ Force input to be interpreted as the given type. Can be: java, jshell, groovy, kotlin, or markdown
+
+*--jsh*::
+ Force input to be interpreted with jsh/jshell. Deprecated: use '--source-type jshell'
*--catalog*=__::
Path to catalog file to be used instead of the default
-*--[no-]cds*::
- If specified Class Data Sharing (CDS) will be used for building and running (requires Java 13+)
+*-j*, *--java*=__::
+ JDK version to use for running the script.
-*--config*=__::
- Path to config file to be used instead of the default
+*-m*, *--main*=__::
+ Main class to use when running. Used primarily for running jar's. Can be a glob pattern using ? and *.
-*--cp, --class-path*=__::
- Add class path entries.
+*--module*=__::
+ Treat resource as a module. Optionally with the given module name
-*-d*, *--debug*[=__]::
- Launch with java debug enabled. Set host/port or provide key/value list of JPDA options (default: null)
+*-C*, *--compile-option*=__::
+ Options to pass to the compiler
-*-D*, __::
+*--manifest*=__::
+
+
+*--[no-]integrations*::
+ Enable or disable integration execution (default: true)
+
+*-D*, *--properties*=__::
set a system property
-*--deps*=__::
+*--deps*=__::
Add additional dependencies (Use commas to separate them).
-*--description*=__::
- A description for the alias
+*--repos*=__::
+ Add additional repositories.
-*--docs*=__::
- Documentation reference for the alias
+*--cp*, *--class-path*=__::
+ Add class path entries.
-*--ea, --enableassertions*::
- Enable assertions
+*--ignore-transitive-repositories*, *--itr*::
+ Ignore remote repositories found in transitive dependencies
-*--enable-preview*::
- Activate Java preview features
+*-n*, *--native*::
+ Build using native-image
-*--esa, --enablesystemassertions*::
- Enable system assertions
+*-N*, *--native-option*=__::
+ Options to pass to the native image tool
-*-f*, *--file*=__::
- Path to the catalog file to use
+*-R*, *--runtime-option*, *--java-options*=__::
+ Options to pass to the Java runtime
-*--files*=__::
- Add additional files.
+*--jfr*=__::
+ Launch with Java Flight Recorder enabled.
-*--force*::
- Force overwriting of existing alias
+*-d*, *--debug*=__::
+ Launch with java debug enabled. Set host/port or provide key/value list of JPDA options (default: ${DEFAULT-VALUE})
-*--fresh*::
- Make sure we use fresh (i.e. non-cached) resources.
+*--enableassertions*, *--ea*::
+ Enable assertions
-*-g*, *--global*::
- Use the global (user) catalog file
+*--enablesystemassertions*, *--esa*::
+ Enable system assertions
-*-h*, *--help*::
- Display help/info. Use 'jbang -h' for detailed usage.
+*--javaagent*=__::
+
+
+*--[no-]cds*::
+ If specified Class Data Sharing (CDS) will be used for building and running (requires Java 13+)
*-i*, *--interactive*::
Activate interactive mode
-*--insecure*::
- Enable insecure trust of all SSL certificates.
-
-*--[no-]integrations*::
- Enable integration execution (default: true)
-
-*--itr, --ignore-transitive-repositories*::
- Ignore remote repositories found in transitive dependencies
-
-*-j*, *--java*=__::
- JDK version to use for running the script.
-
-*--javaagent*=__::
-
+*-g*, *--global*::
+ Use the global (user) catalog file
-*--jfr*[=__]::
- Launch with Java Flight Recorder enabled.
+*-f*, *--file*=__::
+ Path to the catalog file to use
-*--jsh*::
- Force input to be interpreted with jsh/jshell. Deprecated: use '--source-type jshell'
+*--description*=__::
+ A description for the alias
-*-m*, *--main*=__::
- Main class to use when running. Used primarily for running jar's.
+*--name*=__::
+ A name for the alias
-*--manifest*=__::
-
+*--force*::
+ Force overwriting of existing alias
-*--module*[=__]::
- Treat resource as a module. Optionally with the given module name
+*--enable-preview*::
+ Activate Java preview features
-*-n*, *--native*::
- Build using native-image
+*--docs*=__::
+ Documentation reference for the alias
-*-N*, *--native-option*=__::
- Options to pass to the native image tool
+*--config*=__::
+ Path to config file to be used instead of the default
-*--name*=__::
- A name for the alias
+*--insecure*::
+ Enable insecure trust of all SSL certificates.
-*-o*, *--offline*::
- Work offline. Fail-fast if dependencies are missing. No connections will be attempted
+*--verbose*::
+ jbang will be verbose on what it does.
*--quiet*::
jbang will be quiet, only print when error occurs.
-*-R*, *--java-options, --runtime-option*=__::
- Options to pass to the Java runtime
-
-*--repos*=__::
- Add additional repositories.
+*-o*, *--offline*::
+ Work offline. Fail-fast if dependencies are missing.
-*-s*, *--sources*=__::
- Add additional sources.
+*--fresh*::
+ Make sure we use fresh (i.e. non-cached) resources.
-*-T*, *--source-type*=__::
- Force input to be interpreted as the given type. Can be: java, jshell, groovy, kotlin, or markdown
+*--preview*::
+ Enable jbang preview features
-*--verbose*::
- jbang will be verbose on what it does.
+*-x*, *--stacktrace*::
+ Print exceptions stacktraces to stderr (even when quiet).
// end::picocli-generated-man-section-options[]
// tag::picocli-generated-man-section-arguments[]
== Arguments
-[__]::
- A reference to a source file
+__::
+ A file or URL to a Java code file
-[_params_...]::
+__::
Parameters to pass on to the script
// end::picocli-generated-man-section-arguments[]
diff --git a/docs/modules/cli/pages/jbang-alias-list.adoc b/docs/modules/cli/pages/jbang-alias-list.adoc
index 2106c31a0..7f208b866 100644
--- a/docs/modules/cli/pages/jbang-alias-list.adoc
+++ b/docs/modules/cli/pages/jbang-alias-list.adoc
@@ -1,9 +1,9 @@
-// This is a generated documentation file based on picocli
-// To change it update the picocli code or the genrator
+// This is a generated documentation file based on aesh
+// To change it update the aesh code or the generator
// tag::picocli-generated-full-manpage[]
// tag::picocli-generated-man-section-header[]
:doctype: manpage
-:manmanual: jbang Manual
+:manmanual: alias Manual
:man-linkstyle: pass:[blue R < >]
= jbang-alias-list(1)
@@ -12,16 +12,14 @@
// tag::picocli-generated-man-section-name[]
== Name
-jbang-alias-list - Lists locally defined aliases or from the given catalog.
+alias-list - Lists locally defined aliases or from the given catalog.
// end::picocli-generated-man-section-name[]
// tag::picocli-generated-man-section-synopsis[]
== Synopsis
-*jbang alias list* *-o* [*-gh*] *--fresh* [*--insecure*] *--quiet* [*--show-origin*]
- *--verbose* [*--config*=__] [*-f*=__]
- [*--format*=__] [_catalogName_]
+*alias list* [*-h*] [*-g*] [*-f*=__] [*--show-origin*] [*--format*=__] [*--config*=__] [*--insecure*] [*--verbose*] [*--quiet*] [*-o*] [*--fresh*] [*--preview*] [*-x*] [__]
// end::picocli-generated-man-section-synopsis[]
@@ -35,45 +33,51 @@ Lists locally defined aliases or from the given catalog.
// tag::picocli-generated-man-section-options[]
== Options
-*--config*=__::
- Path to config file to be used instead of the default
+*-h*, *--help*::
+ Display help (use --help=all for all options)
+
+*-g*, *--global*::
+ Use the global (user) catalog file
-*-f*, *--file*=__::
+*-f*, *--file*=__::
Path to the catalog file to use
+*--show-origin*::
+ Show the origin of the alias
+
*--format*=__::
Specify output format ('text' or 'json')
-*--fresh*::
- Make sure we use fresh (i.e. non-cached) resources.
-
-*-g*, *--global*::
- Use the global (user) catalog file
-
-*-h*, *--help*::
- Display help/info. Use 'jbang -h' for detailed usage.
+*--config*=__::
+ Path to config file to be used instead of the default
*--insecure*::
Enable insecure trust of all SSL certificates.
-*-o*, *--offline*::
- Work offline. Fail-fast if dependencies are missing. No connections will be attempted
+*--verbose*::
+ jbang will be verbose on what it does.
*--quiet*::
jbang will be quiet, only print when error occurs.
-*--show-origin*::
- Show the origin of the alias
+*-o*, *--offline*::
+ Work offline. Fail-fast if dependencies are missing.
-*--verbose*::
- jbang will be verbose on what it does.
+*--fresh*::
+ Make sure we use fresh (i.e. non-cached) resources.
+
+*--preview*::
+ Enable jbang preview features
+
+*-x*, *--stacktrace*::
+ Print exceptions stacktraces to stderr (even when quiet).
// end::picocli-generated-man-section-options[]
// tag::picocli-generated-man-section-arguments[]
== Arguments
-[_catalogName_]::
+__::
The name of a catalog
// end::picocli-generated-man-section-arguments[]
diff --git a/docs/modules/cli/pages/jbang-alias-remove.adoc b/docs/modules/cli/pages/jbang-alias-remove.adoc
index df9fc110d..34317d7db 100644
--- a/docs/modules/cli/pages/jbang-alias-remove.adoc
+++ b/docs/modules/cli/pages/jbang-alias-remove.adoc
@@ -1,9 +1,9 @@
-// This is a generated documentation file based on picocli
-// To change it update the picocli code or the genrator
+// This is a generated documentation file based on aesh
+// To change it update the aesh code or the generator
// tag::picocli-generated-full-manpage[]
// tag::picocli-generated-man-section-header[]
:doctype: manpage
-:manmanual: jbang Manual
+:manmanual: alias Manual
:man-linkstyle: pass:[blue R < >]
= jbang-alias-remove(1)
@@ -12,15 +12,14 @@
// tag::picocli-generated-man-section-name[]
== Name
-jbang-alias-remove - Remove existing alias.
+alias-remove - Remove existing alias.
// end::picocli-generated-man-section-name[]
// tag::picocli-generated-man-section-synopsis[]
== Synopsis
-*jbang alias remove* *-o* [*-gh*] *--fresh* [*--insecure*] *--quiet* *--verbose*
- [*--config*=__] [*-f*=__] _name_
+*alias remove* [*-h*] [*-g*] [*-f*=__] [*--config*=__] [*--insecure*] [*--verbose*] [*--quiet*] [*-o*] [*--fresh*] [*--preview*] [*-x*] [__]
// end::picocli-generated-man-section-synopsis[]
@@ -34,39 +33,45 @@ Remove existing alias.
// tag::picocli-generated-man-section-options[]
== Options
-*--config*=__::
- Path to config file to be used instead of the default
-
-*-f*, *--file*=__::
- Path to the catalog file to use
-
-*--fresh*::
- Make sure we use fresh (i.e. non-cached) resources.
+*-h*, *--help*::
+ Display help (use --help=all for all options)
*-g*, *--global*::
Use the global (user) catalog file
-*-h*, *--help*::
- Display help/info. Use 'jbang -h' for detailed usage.
+*-f*, *--file*=__::
+ Path to the catalog file to use
+
+*--config*=__::
+ Path to config file to be used instead of the default
*--insecure*::
Enable insecure trust of all SSL certificates.
-*-o*, *--offline*::
- Work offline. Fail-fast if dependencies are missing. No connections will be attempted
+*--verbose*::
+ jbang will be verbose on what it does.
*--quiet*::
jbang will be quiet, only print when error occurs.
-*--verbose*::
- jbang will be verbose on what it does.
+*-o*, *--offline*::
+ Work offline. Fail-fast if dependencies are missing.
+
+*--fresh*::
+ Make sure we use fresh (i.e. non-cached) resources.
+
+*--preview*::
+ Enable jbang preview features
+
+*-x*, *--stacktrace*::
+ Print exceptions stacktraces to stderr (even when quiet).
// end::picocli-generated-man-section-options[]
// tag::picocli-generated-man-section-arguments[]
== Arguments
-_name_::
+__::
The name of the alias
// end::picocli-generated-man-section-arguments[]
diff --git a/docs/modules/cli/pages/jbang-alias.adoc b/docs/modules/cli/pages/jbang-alias.adoc
index 5d0ec19e8..3e43be2f0 100644
--- a/docs/modules/cli/pages/jbang-alias.adoc
+++ b/docs/modules/cli/pages/jbang-alias.adoc
@@ -1,5 +1,5 @@
-// This is a generated documentation file based on picocli
-// To change it update the picocli code or the genrator
+// This is a generated documentation file based on aesh
+// To change it update the aesh code or the generator
// tag::picocli-generated-full-manpage[]
// tag::picocli-generated-man-section-header[]
:doctype: manpage
@@ -19,7 +19,7 @@ jbang-alias - Manage aliases for scripts.
// tag::picocli-generated-man-section-synopsis[]
== Synopsis
-*jbang alias* *-o* [*-h*] *--fresh* *--quiet* *--verbose* [COMMAND]
+*jbang alias* [*-h*] [*--config*=__] [*--insecure*] [*--verbose*] [*--quiet*] [*-o*] [*--fresh*] [*--preview*] [*-x*]
// end::picocli-generated-man-section-synopsis[]
@@ -33,21 +33,33 @@ Manage aliases for scripts.
// tag::picocli-generated-man-section-options[]
== Options
-*--fresh*::
- Make sure we use fresh (i.e. non-cached) resources.
-
*-h*, *--help*::
- Display help/info. Use 'jbang -h' for detailed usage.
+ Display help (use --help=all for all options)
-*-o*, *--offline*::
- Work offline. Fail-fast if dependencies are missing. No connections will be attempted
+*--config*=__::
+ Path to config file to be used instead of the default
-*--quiet*::
- jbang will be quiet, only print when error occurs.
+*--insecure*::
+ Enable insecure trust of all SSL certificates.
*--verbose*::
jbang will be verbose on what it does.
+*--quiet*::
+ jbang will be quiet, only print when error occurs.
+
+*-o*, *--offline*::
+ Work offline. Fail-fast if dependencies are missing.
+
+*--fresh*::
+ Make sure we use fresh (i.e. non-cached) resources.
+
+*--preview*::
+ Enable jbang preview features
+
+*-x*, *--stacktrace*::
+ Print exceptions stacktraces to stderr (even when quiet).
+
// end::picocli-generated-man-section-options[]
// tag::picocli-generated-man-section-arguments[]
diff --git a/docs/modules/cli/pages/jbang-app-install.adoc b/docs/modules/cli/pages/jbang-app-install.adoc
index 9b176c1cd..600f9525c 100644
--- a/docs/modules/cli/pages/jbang-app-install.adoc
+++ b/docs/modules/cli/pages/jbang-app-install.adoc
@@ -1,9 +1,9 @@
-// This is a generated documentation file based on picocli
-// To change it update the picocli code or the genrator
+// This is a generated documentation file based on aesh
+// To change it update the aesh code or the generator
// tag::picocli-generated-full-manpage[]
// tag::picocli-generated-man-section-header[]
:doctype: manpage
-:manmanual: jbang Manual
+:manmanual: app Manual
:man-linkstyle: pass:[blue R < >]
= jbang-app-install(1)
@@ -12,26 +12,14 @@
// tag::picocli-generated-man-section-name[]
== Name
-jbang-app-install - Install a script as a command.
+app-install - Install a script as a command.
// end::picocli-generated-man-section-name[]
// tag::picocli-generated-man-section-synopsis[]
== Synopsis
-*jbang app install* *-o* [*-hin*] [*--[no-]cds*] [*--ea*] [*--enable-preview*] [*--esa*]
- [*--force*] *--fresh* [*--insecure*] [*--[no-]integrations*] [*--itr*]
- [*--jsh*] [*--no-build*] *--quiet* *--verbose* [*--jfr*
- [=__]] [*--module*[=__]] [*-d*
- [=__]]... [*--build-dir*=__]
- [*--catalog*=__] [*--config*=__] [*-j*=__]
- [*-m*=__] [*--name*=__] [*-T*=__]
- [*-C*=__]... [*--cp*=__]...
- [*-D*=__]... [*--deps*=__]...
- [*--files*=__]... [*--javaagent*=__]...
- [*--manifest*=__]... [*-N*=__]...
- [*-R*=__]... [*--repos*=__]...
- [*-s*=__]... [__] [__...]
+*app install* [*-h*] [*-R*=__] [*--jfr*=__] [*-d*=__] [*--enableassertions*] [*--enablesystemassertions*] [*--javaagent*=__] [*--cds*] [*-i*] [*--force*] [*--no-build*] [*--name*=__] [*-s*=__] [*--files*=__] [*-T*=__] [*--jsh*] [*--catalog*=__] [*-j*=__] [*-m*=__] [*--module*=__] [*-C*=__] [*--manifest*=__] [*--integrations*] [*-D*=__] [*--deps*=__] [*--repos*=__] [*--cp*=__] [*--ignore-transitive-repositories*] [*-n*] [*-N*=__] [*--build-dir*=__] [*--enable-preview*] [*--config*=__] [*--insecure*] [*--verbose*] [*--quiet*] [*-o*] [*--fresh*] [*--preview*] [*-x*] [__] [__...]
// end::picocli-generated-man-section-synopsis[]
@@ -45,129 +33,135 @@ Install a script as a command.
// tag::picocli-generated-man-section-options[]
== Options
-*--build-dir*=__::
- Use given directory for build results
+*-h*, *--help*::
+ Display help (use --help=all for all options)
-*-C*, *--compile-option*=__::
- Options to pass to the compiler
+*-R*, *--runtime-option*, *--java-options*=__::
+ Options to pass to the Java runtime
-*--catalog*=__::
- Path to catalog file to be used instead of the default
+*--jfr*=__::
+ Launch with Java Flight Recorder enabled.
-*--[no-]cds*::
- If specified Class Data Sharing (CDS) will be used for building and running (requires Java 13+)
+*-d*, *--debug*=__::
+ Launch with java debug enabled. Set host/port or provide key/value list of JPDA options (default: ${DEFAULT-VALUE})
-*--config*=__::
- Path to config file to be used instead of the default
+*--enableassertions*, *--ea*::
+ Enable assertions
-*--cp, --class-path*=__::
- Add class path entries.
+*--enablesystemassertions*, *--esa*::
+ Enable system assertions
-*-d*, *--debug*[=__]::
- Launch with java debug enabled. Set host/port or provide key/value list of JPDA options (default: null)
+*--javaagent*=__::
+
-*-D*, __::
- set a system property
+*--[no-]cds*::
+ If specified Class Data Sharing (CDS) will be used for building and running (requires Java 13+)
-*--deps*=__::
- Add additional dependencies (Use commas to separate them).
+*-i*, *--interactive*::
+ Activate interactive mode
-*--ea, --enableassertions*::
- Enable assertions
+*--force*::
+ Force re-installation
-*--enable-preview*::
- Activate Java preview features
+*--no-build*::
+ Don't pre-build the code before installation
-*--esa, --enablesystemassertions*::
- Enable system assertions
+*--name*=__::
+ A name for the command
-*--files*=__::
- Add additional files.
+*-s*, *--sources*=__::
+ Add additional sources.
-*--force*::
- Force re-installation
+*--files*=__::
+ Add additional files.
-*--fresh*::
- Make sure we use fresh (i.e. non-cached) resources.
+*-T*, *--source-type*=__::
+ Force input to be interpreted as the given type. Can be: java, jshell, groovy, kotlin, or markdown
-*-h*, *--help*::
- Display help/info. Use 'jbang -h' for detailed usage.
+*--jsh*::
+ Force input to be interpreted with jsh/jshell. Deprecated: use '--source-type jshell'
-*-i*, *--interactive*::
- Activate interactive mode
+*--catalog*=__::
+ Path to catalog file to be used instead of the default
-*--insecure*::
- Enable insecure trust of all SSL certificates.
+*-j*, *--java*=__::
+ JDK version to use for running the script.
-*--[no-]integrations*::
- Enable integration execution (default: true)
+*-m*, *--main*=__::
+ Main class to use when running. Used primarily for running jar's. Can be a glob pattern using ? and *.
-*--itr, --ignore-transitive-repositories*::
- Ignore remote repositories found in transitive dependencies
+*--module*=__::
+ Treat resource as a module. Optionally with the given module name
-*-j*, *--java*=_