= Picocli Code Generation :revnumber: 4.6.1 :revdate: 2021-01-03 :toc: left :numbered: :toclevels: 4 :source-highlighter: coderay //:source-highlighter: highlightjs //:highlightjs-theme: darkula :icons: font ifdef::env-github[] :caution-caption: :fire: :tip-caption: :bulb: endif::[] image::https://picocli.info/images/logo/horizontal-400x150.png[picocli,height="150px"] == About `picocli-codegen` The `picocli-codegen` (Picocli Code Generation) module contains tools for generating configuration files and documentation for picocli-based applications. This module also includes an annotation processor that can build a model from the picocli annotations at compile time rather than at runtime. The annotation processor allows many of the tools to be invoked automatically as part of the build without configuration. If a tool does not have an annotation processor wrapper (yet), it can be invoked on the command line, and can be scripted to be invoked automatically as part of building your project. As of picocli version 4.2, this module has three major use cases: * **Compile time error checking**. The annotation processor shows errors for invalid annotations and attributes immediately when you compile, instead of during testing at runtime, resulting in shorter feedback cycles. * **GraalVm native images**. To create a GraalVM native image for a picocli application, https://github.com/oracle/graal/blob/master/substratevm/BuildConfiguration.md[configuration] is needed. The `ReflectionConfigGenerator`, `ResourceConfigGenerator` and `DynamicProxyGenerator` tools can generate configuration files for https://github.com/oracle/graal/blob/master/substratevm/Reflection.md[reflection], https://github.com/oracle/graal/blob/master/substratevm/Resources.md[resources] and https://github.com/oracle/graal/blob/master/substratevm/DynamicProxy.md[dynamic proxies], respectively. + The annotation processor embeds these three tools and generates the configuration files under `META-INF/native-image/picocli-generated/$project` during compilation, to be included in the application jar. By embedding these configuration files, your jar is instantly GraalVM-enabled. In most cases no further configuration is needed when generating a native image. * **Generate Documentation**. The `ManPageGenerator` tool can generate AsciiDoc documentation for picocli applications. AsciiDoc is a lightweight markup language that can easily can be converted to unix man pages, HTML and PDF with the wonderful https://asciidoctor.org/docs/user-manual/#man-pages[asciidoctor] tool. == Generate GraalVM Configurations with the Annotation Processor To build a GraalVM native image for a picocli-based application, configuration files are needed to tell the GraalVM `native-image` generator tool which classes, methods and fields will be accessed reflectively, and which resources and dynamic proxies the application will use. The `picocli-codegen` module has tools that generate these configuration files for a picocli-based application. The annotation processor in the `picocli-codegen` jar wraps these tools so they are executed automatically during compilation. The annotation processor generates and updates https://github.com/oracle/graal/blob/master/substratevm/BuildConfiguration.md[GraalVM configuration] files under `META-INF/native-image/picocli-generated/$project` during compilation, to be included in the application jar. This includes configuration files for https://github.com/oracle/graal/blob/master/substratevm/Reflection.md[reflection], https://github.com/oracle/graal/blob/master/substratevm/Resources.md[resources] and https://github.com/oracle/graal/blob/master/substratevm/DynamicProxy.md[dynamic proxies]. By embedding these configuration files, your jar is instantly GraalVM-enabled. In most cases no further configuration is needed when generating a native image. TIP: It is recommended that you configure the `$project` location for your project to ensure the configuration files are in a unique location when jars are shaded into an uberjar, see <> below. === Enabling the Annotation Processor Since Java 6, annotation processing is part of the standard `javac` compiler, but many IDEs and build tools require something extra to enable annotation processing. ==== IDE https://immutables.github.io/apt.html[This page] shows the steps to configure Eclipse and IntelliJ IDEA to enable annotation processing. ==== Maven In Maven, use `annotationProcessorPaths` in the `configuration` of the `maven-compiler-plugin`. This requires `maven-compiler-plugin` plugin version 3.5 or higher. ```xml org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin-version} info.picocli picocli-codegen 4.6.1 ``` An alternative that works with older versions of the `maven-compiler-plugin` is to specify the `picocli-codegen` module on the classpath as a `provided` dependency. This also prevents the `picocli-codegen` module from being included in the artifact the module produces as a transitive dependency. ```xml info.picocli picocli 4.6.1 info.picocli picocli-codegen 4.6.1 provided ``` See <> below. ==== Gradle Use the `annotationProcessor` path in Gradle https://docs.gradle.org/4.6/release-notes.html#convenient-declaration-of-annotation-processor-dependencies[4.6 and higher]: ```groovy dependencies { implementation 'info.picocli:picocli:4.6.1' annotationProcessor 'info.picocli:picocli-codegen:4.6.1' } ``` For Gradle versions prior to 4.6, use `compileOnly`, to prevent the `picocli-codegen` jar from being a transitive dependency included in the artifact the module produces. ```groovy dependencies { implementation 'info.picocli:picocli:4.6.1' compileOnly 'info.picocli:picocli-codegen:4.6.1' } ``` ==== Kotlin Projects Using Maven Add an execution of the `kapt` goal from `kotlin-maven-plugin` before `compile`: ``` kotlin-maven-plugin org.jetbrains.kotlin ${kotlin.version} kapt kapt src/main/kotlin src/main/java info.picocli picocli-codegen 4.6.1 compile ``` JetBrains' https://github.com/JetBrains/kotlin-examples/tree/master/maven/dagger-maven-example[Kotlin Examples repository] has a complete example complete sample project showing the use of Kotlin, Maven and Dagger. ==== Kotlin Projects Using Gradle Kotlin projects should add the `kotlin-kapt` plugin to enable the Kotlin Annotation processing tool (kapt), then replace `annotationProcessor` with `kapt`: ``` apply plugin: 'kotlin-kapt' // required dependencies { // ... kapt 'info.picocli:picocli-codegen:4.6.1' } ``` And replace `compileJava.options.compilerArgs` with `kapt.arguments`: ``` kapt { arguments { arg("project", "${project.group}/${project.name}") } } ``` === Picocli Processor Options The picocli annotation processor supports the options below. ==== Recommended Options * `project` - output subdirectory The generated files are written to `META-INF/native-image/picocli-generated/${project}`. The `project` option can be omitted, but it is a good idea to specify the `project` option with a unique value for your project (e.g. `${groupId}/${artifactId}`) if your jar may be https://stackoverflow.com/a/49811665[shaded] with other jars into an uberjar. ==== Other Options * `verbose` - (from picocli 4.3) print NOTE-level diagnostic messages to the console * `other.resource.patterns` - comma-separated list of regular expressions matching additional resources to include in the image * `other.resource.bundles` - comma-separated list of the base names of additional resource bundles to include in the image * `other.proxy.interfaces` - comma-separated list of the fully qualified class names of additional interfaces for which to generate proxy classes when building the image * `disable.proxy.config` - disable the <> tool so no `proxy-config.json` file is generated * `disable.reflect.config` - disable the <> tool so no `reflect-config.json` file is generated * `disable.resource.config` - disable the <> tool so no `resources-config.json` file is generated ==== Javac To pass an annotation processor option with `javac`, specify the `-A` command line option: ---- javac -Aproject=org.myorg.myproject/myapp -cp ... ---- The `-A` option lets you pass options to annotation processors. See the https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html[javac documentation] for details. ==== Maven To set an annotation processor option in Maven, you need to use the `maven-compiler-plugin` and configure the `compilerArgs` section. [source,xml] ---- org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin-version} -Aproject=${groupId}/${artifactId} ---- See https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html for details. === Gradle Example To set an annotation processor option in Gradle, add these options to the `options.compilerArgs` list in the `compileJava` block. [source,groovy] ---- compileJava { // minimum 1.6 sourceCompatibility = ${java-version} targetCompatibility = ${java-version} options.compilerArgs += ["-Aproject=${project.group}/${project.name}"] } ---- See the https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html[Gradle documentation] for details. === Gradle Example for Kotlin Projects In Kotlin projects using Gradle, replace `compileJava.options.compilerArgs` with `kapt.arguments`: ``` kapt { arguments { arg("project", "${project.group}/${project.name}") } } ``` See the https://kotlinlang.org/docs/reference/kapt.html[Kotlin Annotation Processing documentation] for details. == Generate GraalVM Configurations Manually The annotation processor is the recommended way to generate configuration files for GraalVM native images, but there may be cases where you want to generate these configuration files manually. For example, if your commands are written in Groovy, the picocli annotation processor will not be able to auto-generate configuration files for your commands, and you need to do some work to invoke the commands in your build. The sections below give details on how to do this. The `picocli-codegen` module contains the following tools to assist with AOT compilation to GraalVM native image builds: * ReflectionConfigGenerator * ResourceConfigGenerator * DynamicProxyConfigGenerator The generated configuration files can be supplied to the `native-image` tool via command line options like `-H:ReflectionConfigurationFiles=/path/to/reflect-config.json`, or alternatively by placing them in a `META-INF/native-image/` directory on the class path, for example, in a JAR file used in the image build. This directory (or any of its subdirectories) is searched for files with the names `reflect-config.json`, `proxy-config.json` and `resource-config.json`, which are then automatically included in the build. Not all of those files must be present. When multiple files with the same name are found, all of them are included. See also the SubstrateVM https://github.com/oracle/graal/blob/master/substratevm/BuildConfiguration.md[configuration documentation]. === ReflectionConfigGenerator GraalVM has https://github.com/oracle/graal/blob/master/substratevm/Reflection.md[limited support for Java reflection] and it needs to know ahead of time the reflectively accessed program elements. `ReflectionConfigGenerator` generates a JSON String with the program elements that will be accessed reflectively in a picocli-based application, in order to compile this application ahead-of-time into a native executable with GraalVM. The <> manual page for the `ReflectionConfigGenerator` tool https://picocli.info/man/gen-reflect-config.html[is here]. The output of `ReflectionConfigGenerator` is intended to be passed to the `-H:ReflectionConfigurationFiles=/path/to/reflect-config.json` option of the `native-image` GraalVM utility, or placed in a `META-INF/native-image/` subdirectory of the JAR. This allows picocli-based applications to be compiled to a native image. See https://picocli.info/picocli-on-graalvm.html[Picocli on GraalVM: Blazingly Fast Command Line Apps] for details. ==== Generating Reflection Configuration During the Build _Note that the <> does this automatically. The below is only of interest if you cannot use the annotation processor for some reason._ The `--output` option can be used to specify the path of the file to write the configuration to. When this option is omitted, the output is sent to standard out. The `ReflectionConfigGenerator` tool accepts any number of fully qualified class names of command classes (classes with picocli annotations like `@Command`, `@Option` and `@Parameters`). The resulting configuration file will contain entries for the reflected elements of all specified classes. ===== Maven For Maven, add an `exec:java` goal to generate a Graal reflection configuration file with the `ReflectionConfigGenerator` tool. This example uses the `process-classes` phase of the build, there are http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html[alternatives]. Note that the `picocli-codegen` module is only added as a dependency for the `exec` plugin, so it does not need to be added to the project dependencies. [source,xml] ---- org.codehaus.mojo exec-maven-plugin 3.0.0 generateGraalReflectionConfig process-classes java true true picocli.codegen.aot.graalvm.ReflectionConfigGenerator --output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json com.your.package.YourCommand1 com.your.package.YourCommand2 info.picocli picocli-codegen 4.6.1 jar ---- ===== Gradle For Gradle, add a custom configuration for the `picocli-codegen` module to your `gradle.build`. This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build. [source,groovy] ---- configurations { generateConfig } dependencies { implementation 'info.picocli:picocli:4.6.1' generateConfig 'info.picocli:picocli-codegen:4.6.1' } ---- Then, add a custom task to run the `ReflectionConfigGenerator` tool. This example generates the file during the `assemble` lifecycle task, there are https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_tasks[alternatives]. [source,groovy] ---- task(generateGraalReflectionConfig, dependsOn: 'classes', type: JavaExec) { main = 'picocli.codegen.aot.graalvm.ReflectionConfigGenerator' classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/reflect-config.json" args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2'] } assemble.dependsOn generateGraalReflectionConfig ---- === ResourceConfigGenerator The GraalVM native-image builder by default will not integrate any of the https://github.com/oracle/graal/blob/master/substratevm/Resources.md[classpath resources] into the image it creates. `ResourceConfigGenerator` generates a JSON String with the resource bundles and other classpath resources that should be included in the Substrate VM native image. The <> manual page for the `ResourceConfigGenerator` tool https://picocli.info/man/gen-resource-config.html[is here]. The output of `ResourceConfigGenerator` is intended to be passed to the `-H:ResourceConfigurationFiles=/path/to/reflect-config.json` option of the `native-image` GraalVM utility, or placed in a `META-INF/native-image/` subdirectory of the JAR. This allows picocli-based native image applications to access these resources. ==== Generating Resource Configuration During the Build _Note that the <> does this automatically. The below is only of interest if you cannot use the annotation processor for some reason._ The `--output` option can be used to specify the path of the file to write the configuration to. When this option is omitted, the output is sent to standard out. The `ResourceConfigGenerator` tool accepts any number of fully qualified class names of command classes (classes with picocli annotations like `@Command`, `@Option` and `@Parameters`). The resulting configuration file will contain entries for the resource bundles used in any of the specified commands or their subcommands. The `--bundle` option can be used to specify the base name of additional resource bundle(s) to be included in the image. The `--pattern` option can be used to specify Java regular expressions that match additional resource(s) to be included in the image. ===== Maven For Maven, add an `exec:java` goal to generate a Graal resource configuration file with the `ResourceConfigGenerator` tool. This example uses the `process-classes` phase of the build, there are http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html[alternatives]. Note that the `picocli-codegen` module is only added as a dependency for the `exec` plugin, so it does not need to be added to the project dependencies. [source,xml] ---- org.codehaus.mojo exec-maven-plugin 3.0.0 generateGraalResourceConfig process-classes java true true picocli.codegen.aot.graalvm.ResourceConfigGenerator --output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/resource-config.json com.your.package.YourCommand1 com.your.package.YourCommand2 info.picocli picocli-codegen 4.6.1 jar ---- ===== Gradle For Gradle, add a custom configuration for the `picocli-codegen` module to your `gradle.build`. This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build. [source,groovy] ---- configurations { generateConfig } dependencies { implementation 'info.picocli:picocli:4.6.1' generateConfig 'info.picocli:picocli-codegen:4.6.1' } ---- Then, add a custom task to run the `ResourceConfigGenerator` tool. This example generates the file during the `assemble` lifecycle task, there are https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_tasks[alternatives]. [source,groovy] ---- task(generateGraalResourceConfig, dependsOn: 'classes', type: JavaExec) { main = 'picocli.codegen.aot.graalvm.ResourceConfigGenerator' classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/resource-config.json" args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2'] } assemble.dependsOn generateGraalResourceConfig ---- === DynamicProxyConfigGenerator Substrate VM doesn't provide machinery for generating and interpreting bytecodes at run time. Therefore all dynamic proxy classes https://github.com/oracle/graal/blob/master/substratevm/DynamicProxy.md[need to be generated] at native image build time. `DynamicProxyConfigGenerator` generates a JSON String with the fully qualified interface names for which dynamic proxy classes should be generated at native image build time. The <> manual page for the `DynamicProxyConfigGenerator` tool https://picocli.info/man/gen-proxy-config.html[is here]. The output of `DynamicProxyConfigGenerator` is intended to be passed to the `-H:DynamicProxyConfigurationFiles=/path/to/proxy-config.json` option of the `native-image` GraalVM utility, or placed in a `META-INF/native-image/` subdirectory of the JAR. This allows picocli-based native image applications that use `@Command`-annotated interfaces with `@Option` and `@Parameters`-annotated methods. ==== Generating Dynamic Proxy Configuration During the Build _Note that the <> does this automatically. The below is only of interest if you cannot use the annotation processor for some reason._ The `--output` option can be used to specify the path of the file to write the configuration to. When this option is omitted, the output is sent to standard out. The `DynamicProxyConfigGenerator` tool accepts any number of fully qualified class names of command classes (classes with picocli annotations like `@Command`, `@Option` and `@Parameters`). The resulting configuration file will contain entries for the resource bundles used in any of the specified commands or their subcommands. The `--interface` option can be used to specify the fully qualified class names of additional interfaces to generate dynamic proxy classes for in the native image. ===== Maven For Maven, add an `exec:java` goal to generate a Graal proxy configuration file with the `DynamicProxyConfigGenerator` tool. This example uses the `process-classes` phase of the build, there are http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html[alternatives]. Note that the `picocli-codegen` module is only added as a dependency for the `exec` plugin, so it does not need to be added to the project dependencies. [source,xml] ---- org.codehaus.mojo exec-maven-plugin 3.0.0 generateGraalDynamicProxyConfig process-classes java true true picocli.codegen.aot.graalvm.DynamicProxyConfigGenerator --output=target/classes/META-INF/native-image/${project.groupId}/${project.artifactId}/proxy-config.json com.your.package.YourCommand1 com.your.package.YourCommand2 info.picocli picocli-codegen 4.6.1 jar ---- ===== Gradle For Gradle, add a custom configuration for the `picocli-codegen` module to your `gradle.build`. This allows us to add this module to the classpath of our custom task without adding it as a dependency to the "standard" build. [source,groovy] ---- configurations { generateConfig } dependencies { implementation 'info.picocli:picocli:4.6.1' generateConfig 'info.picocli:picocli-codegen:4.6.1' } ---- Then, add a custom task to run the `DynamicProxyConfigGenerator` tool. This example generates the file during the `assemble` lifecycle task, there are https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_tasks[alternatives]. [source,groovy] ---- task(generateGraalDynamicProxyConfig, dependsOn: 'classes', type: JavaExec) { main = 'picocli.codegen.aot.graalvm.DynamicProxyConfigGenerator' classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath def outputFile = "${buildDir}/resources/main/META-INF/native-image/${project.group}/${project.name}/proxy-config.json" args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2'] } assemble.dependsOn generateGraalDynamicProxyConfig ---- == Generate Documentation The `picocli.codegen.docgen.manpage.ManPageGenerator` tool introduced in picocli 4.2 generates AsciiDoc documentation using the `manpage` doctype and manpage document structure. The generated AsciiDoc files can be converted to HTML, PDF and unix man pages with the https://asciidoctor.org/docs/user-manual/#man-pages[asciidoctor] tool. The generated manual page for the `ManPageGenerator` tool itself https://picocli.info/man/gen-manpage.html[is here]. === Gradle Example Example gradle build.gradle snippet: You will also need the https://asciidoctor.org/docs/asciidoctor-gradle-plugin/[AsciiDoctor Gradle Plugin]. [source,groovy] ---- dependencies { implementation "info.picocli:picocli:4.6.1" annotationProcessor "info.picocli:picocli-codegen:4.6.1" } mainClassName = "my.pkg.MyCommand" task generateManpageAsciiDoc(type: JavaExec) { dependsOn(classes) group = "Documentation" description = "Generate AsciiDoc manpage" classpath(configurations.compile, configurations.annotationProcessor, sourceSets.main.runtimeClasspath) main 'picocli.codegen.docgen.manpage.ManPageGenerator' args mainClassName, "--outdir=${project.buildDir}/generated-picocli-docs", "-v" //, "--template-dir=src/docs/mantemplates" } apply plugin: 'org.asciidoctor.jvm.convert' asciidoctor { dependsOn(generateManpageAsciiDoc) sourceDir = file("${project.buildDir}/generated-picocli-docs") outputDir = file("${project.buildDir}/docs") logDocuments = true outputOptions { backends = ['manpage', 'html5'] } } ---- The `generateManpageAsciiDoc` task generates `$COMMANDNAME.adoc` files with doctype `manpage` in `build/generated-picocli-docs` for each command and subcommand. The `asciidoctor` task converts the generated `$COMMANDNAME.adoc` files in `build/generated-picocli-docs` to `$COMMANDNAME.1` manpage files in `build/docs/manpage/`, and to `$COMMANDNAME.html` HTML files in `build/docs/html5/`. See the link:https://github.com/remkop/picocli/tree/master/picocli-examples/generate-man-pages/example-gradle-project[example-gradle-project] in the `picocli-examples` module for a full working example. === Maven Example You will also need the https://github.com/asciidoctor/asciidoctor-maven-plugin[AsciiDoctor Maven Plugin]. For Maven, add an `exec:java` goal to generate a Graal proxy configuration file with the `ManPageGenerator` tool. This example uses the `process-classes` phase of the build, there are http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html[alternatives]. Note that the `picocli-codegen` module is only added as a dependency for the `exec` plugin, so it does not need to be added to the project dependencies. [source,xml] ---- org.codehaus.mojo exec-maven-plugin 3.0.0 generateManPages process-classes java true true picocli.codegen.docgen.manpage.ManPageGenerator --outdir=${project.build.directory}/generated-picocli-docs com.your.package.YourCommand1 com.your.package.YourCommand2 info.picocli picocli-codegen 4.6.1 jar org.asciidoctor asciidoctor-maven-plugin 2.1.0 output-html process-classes process-asciidoc coderay html5 output-manpage process-classes process-asciidoc coderay manpage ${project.build.directory}/generated-picocli-docs ---- See the link:https://github.com/remkop/picocli/tree/master/picocli-examples/generate-man-pages/example-maven-project[example-maven-project] in the `picocli-examples` module for a full working example. === Customizing with Templates The generated man page is very similar to the online help generated by the command itself when a user specifies the `--help` option. You may want to add more details or extra sections to the man page. To achieve this, the `ManPageGenerator` tool has an option to create an additional "template" file for each generated manpage AsciiDoc file. ==== Templates Concept The generated manpage AsciiDoc files will be regenerated every build. We don't want to edit these files because we would lose our changes every time the files are regenerated. Instead, we will edit "template" files. Template files leverage AsciiDoctor's https://asciidoctor.org/docs/user-manual/#include-directive[include mechanism] to import the contents of the generated manpage AsciiDoc files into a separate file. The template page initially just contains a number of `include::path/to/some.adoc[tag=xxx]` statements. Each `include` statement imports part of a generated manpage AsciiDoc file. You can rearrange these includes and add text after each include to customize the resulting man page. Once we created the template files, we will need to tell the `asciidoctor` tool to take these template files as input instead of the generated manpage AsciiDoc files. The resulting man page will be a mixture of generated and manually edited text. The `ManPageGenerator` tool can generate template files, but template files should not be generated multiple times. They are intended to be generated _only once_, and afterwards be manually updated and maintained. Changes in the generated manpage AsciiDoc files will then be reflected in the final output via the includes, without impacting the additions or modifications you made to the template files. ==== Creating Template Files To create template pages, specify the `--template-dir` option when invoking the `picocli.codegen.docgen.manpage.ManPageGenerator` tool. For example: ---- java -cp $CLASSPATH picocli.codegen.docgen.manpage.ManPageGenerator \ -v --outdir=${project.buildDir}/generated/docs \ --template-dir=src/docs/man-templates \ my.pkg.MyCommand ---- This generates AsciiDoc files with the 'manpage' doctype in `build/generated/docs`, and template files in `src/docs/man-templates`. CAUTION: Do this only once, then remove the `--template-dir` option, so that subsequent `ManPageGenerator` invocations will only update the generated manpage AsciiDoc files and will not overwrite the template files. CAUTION: If the `ManPageGenerator` tool detects an existing template file, it will abort with an error (and exit code 4). The existing template will not be overwritten unless the `--force` option is specified. We can now edit the files in `src/docs/man-templates` and tell the `asciidoctor` tool to generate HTML and man page files in troff format from the files in `src/docs/man-templates`. ==== Using Template Files In its simplest form a template file can include the full generated page with the `picocli-generated-full-manpage` tag. This allows us to add some sections to the end of the page. For example: [subs="+macros,verbatim,quotes"] ---- // src/docs/man-templates/xxx.adoc pass:c[:includedir: ../../../build/generated/docs] pass:c[include::{includedir}/xxx.adoc[tag=picocli-generated-full-manpage]] #== Authors# #My, myself and I.# ---- It is also possible to include the picocli-generated sections individually, so that the generated sections can be customized with additional text that follows the generated text for the section. For example: [subs="+macros,verbatim,quotes"] ---- // src/docs/man-templates/yyy.adoc pass:c[:includedir: ../../../build/generated/docs] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-header]] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-name]] #This is a very good tool that will serve you well.# pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-synopsis]] #pass:c[*mycommand*] [-hVv] [a=VERY] [--different=synopsis]# pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-description]] #Here is one additional description line.# #Here is another additional description line.# pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-options]] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-arguments]] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-commands]] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-exit-status]] pass:c[include::{includedir}/yyy.adoc[tag=picocli-generated-man-section-footer]] #== More Examples# #[%hardbreaks]# #Here are some extra examples:# #abc def ghi jkl mno pq# #abc def ghi jkl mno pq# #abc def ghi jkl mno pq# #== Authors# #All of us.# #== Copyright# #Just hand it out, it's fine.# ---- Then, when invoking the `asciidoctor` tool, specify the directory containing the template files as the source directory. For example: [source,bash] ---- # generate man pages in troff format in build/docs/manpage asciidoctor --backend=manpage --source-dir=src/docs/man-templates --destination-dir=build/docs *.adoc # generate man pages in HTML format in build/docs/html5 asciidoctor --backend=html5 --source-dir=src/docs/man-templates --destination-dir=build/docs *.adoc ----