|
| 1 | +--- |
| 2 | +date: '2026-05-29T12:00:00+02:00' |
| 3 | +draft: false |
| 4 | +title: 'Documentation Generation' |
| 5 | +weight: 18 |
| 6 | +--- |
| 7 | + |
| 8 | +Aesh can generate documentation files from your command metadata in AsciiDoc or Markdown format. This produces one page per command/subcommand, suitable for project documentation sites, man page alternatives, or API reference. |
| 9 | + |
| 10 | +## Quick Start |
| 11 | + |
| 12 | +The simplest way to generate documentation is with the built-in `--aesh-doc` flag: |
| 13 | + |
| 14 | +```bash |
| 15 | +# Generate AsciiDoc to stdout (default) |
| 16 | +$ myapp --aesh-doc |
| 17 | + |
| 18 | +# Generate Markdown |
| 19 | +$ myapp --aesh-doc markdown |
| 20 | + |
| 21 | +# Save to a file |
| 22 | +$ myapp --aesh-doc asciidoc > docs/myapp.adoc |
| 23 | +``` |
| 24 | + |
| 25 | +No code changes needed — this works automatically with the standard `AeshRuntimeRunner` pattern. |
| 26 | + |
| 27 | +## Programmatic API |
| 28 | + |
| 29 | +For build-time generation or more control, use the `DocumentationGenerator` builder: |
| 30 | + |
| 31 | +```java |
| 32 | +import org.aesh.util.doc.DocumentationGenerator; |
| 33 | +import org.aesh.util.doc.DocFormat; |
| 34 | + |
| 35 | +// Generate one file per command/subcommand |
| 36 | +DocumentationGenerator.builder() |
| 37 | + .commandClass(MyCommand.class) |
| 38 | + .outputDir(new File("docs/pages")) |
| 39 | + .format(DocFormat.ASCIIDOC) |
| 40 | + .generate(); |
| 41 | +``` |
| 42 | + |
| 43 | +### Antora Integration |
| 44 | + |
| 45 | +For [Antora](https://antora.org/) documentation sites, set a cross-reference prefix and generate a navigation file: |
| 46 | + |
| 47 | +```java |
| 48 | +DocumentationGenerator.builder() |
| 49 | + .commandClass(MyCommand.class) |
| 50 | + .outputDir(new File("docs/modules/cli/pages")) |
| 51 | + .crossRefPrefix("myapp:cli:") |
| 52 | + .navFile(new File("docs/modules/cli/nav.adoc")) |
| 53 | + .format(DocFormat.ASCIIDOC) |
| 54 | + .generate(); |
| 55 | +``` |
| 56 | + |
| 57 | +This produces: |
| 58 | +- One `.adoc` file per command/subcommand (e.g., `myapp.adoc`, `myapp-run.adoc`) |
| 59 | +- A `nav.adoc` with Antora-compatible `xref:` links |
| 60 | +- Cross-reference links between pages using the configured prefix |
| 61 | + |
| 62 | +### Single Command Output |
| 63 | + |
| 64 | +Generate documentation for a single command as a string: |
| 65 | + |
| 66 | +```java |
| 67 | +String doc = DocumentationGenerator.builder() |
| 68 | + .commandClass(MyCommand.class) |
| 69 | + .format(DocFormat.MARKDOWN) |
| 70 | + .generateSingle(); |
| 71 | +``` |
| 72 | + |
| 73 | +## Generated Sections |
| 74 | + |
| 75 | +Each generated page includes: |
| 76 | + |
| 77 | +| Section | Content | |
| 78 | +|---------|---------| |
| 79 | +| **NAME** | Command name and description | |
| 80 | +| **SYNOPSIS** | Formatted usage with options, arguments, and `[COMMAND]` placeholder for groups | |
| 81 | +| **DESCRIPTION** | Command description from the annotation | |
| 82 | +| **OPTIONS** | All visible options with short/long names, value placeholders, defaults, aliases, and negatable display | |
| 83 | +| **ARGUMENTS** | Positional parameters with labels | |
| 84 | +| **COMMANDS** | Subcommands for group commands, with cross-reference links | |
| 85 | + |
| 86 | +### HelpSectionProvider Content |
| 87 | + |
| 88 | +If your command uses a [`HelpSectionProvider`](../advanced-topics), its content is included: |
| 89 | + |
| 90 | +- **Header** — inserted between DESCRIPTION and OPTIONS |
| 91 | +- **Additional sections** — rendered as separate sections (e.g., EXAMPLES) |
| 92 | +- **Footer** — appended at the end |
| 93 | + |
| 94 | +```java |
| 95 | +@CommandDefinition(name = "deploy", description = "Deploy app", |
| 96 | + helpSectionProvider = DeployHelpProvider.class) |
| 97 | +public class DeployCommand implements Command<CommandInvocation> { ... } |
| 98 | + |
| 99 | +public class DeployHelpProvider implements HelpSectionProvider { |
| 100 | + @Override |
| 101 | + public String getHeader() { |
| 102 | + return "Deploys the application to the configured environment."; |
| 103 | + } |
| 104 | + |
| 105 | + @Override |
| 106 | + public Map<String, List<HelpEntry>> getAdditionalSections() { |
| 107 | + return Map.of("Examples", List.of( |
| 108 | + new HelpEntry("deploy --env prod myapp", "Deploy to production"), |
| 109 | + new HelpEntry("deploy --force myapp", "Force redeploy"))); |
| 110 | + } |
| 111 | + |
| 112 | + @Override |
| 113 | + public String getFooter() { |
| 114 | + return "Report bugs to https://github.com/example/deploy/issues"; |
| 115 | + } |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +### Option Rendering Features |
| 120 | + |
| 121 | +The generator handles all option features: |
| 122 | + |
| 123 | +- **Aliases** — `--ea` shown alongside `--enableassertions` |
| 124 | +- **Negatable options** — displayed as `--[no-]verbose` |
| 125 | +- **Value placeholders** — `--config=<config>`, `<key>=<value>` for option groups |
| 126 | +- **Default values** — shown as `Default: \`dev\`` |
| 127 | +- **Hidden option filtering** — `OptionVisibility.HIDDEN` options are excluded |
| 128 | +- **Multi-line descriptions** — text blocks and `\n` in descriptions render properly |
| 129 | + |
| 130 | +## Output Formats |
| 131 | + |
| 132 | +### AsciiDoc |
| 133 | + |
| 134 | +```asciidoc |
| 135 | += DEPLOY |
| 136 | + |
| 137 | +== NAME |
| 138 | + |
| 139 | +deploy -- Deploy an application |
| 140 | + |
| 141 | +== SYNOPSIS |
| 142 | + |
| 143 | +[source] |
| 144 | +---- |
| 145 | +deploy [-f] [-e=<environment>] [-D<key>=<value>] <application> |
| 146 | +---- |
| 147 | + |
| 148 | +== OPTIONS |
| 149 | + |
| 150 | +*-e*, *--environment*=<environment>:: |
| 151 | +Target environment |
| 152 | ++ |
| 153 | +Default: `dev` |
| 154 | + |
| 155 | +*-f*, *--force*:: |
| 156 | +Force deployment |
| 157 | +``` |
| 158 | + |
| 159 | +### Markdown |
| 160 | + |
| 161 | +```markdown |
| 162 | +# DEPLOY |
| 163 | + |
| 164 | +## NAME |
| 165 | + |
| 166 | +deploy -- Deploy an application |
| 167 | + |
| 168 | +## SYNOPSIS |
| 169 | + |
| 170 | +\`\`\` |
| 171 | +deploy [-f] [-e=<environment>] [-D<key>=<value>] <application> |
| 172 | +\`\`\` |
| 173 | + |
| 174 | +## OPTIONS |
| 175 | + |
| 176 | +### `-e`, `--environment=<environment>` |
| 177 | + |
| 178 | +Target environment |
| 179 | + |
| 180 | +Default: `dev` |
| 181 | + |
| 182 | +### `-f`, `--force` |
| 183 | + |
| 184 | +Force deployment |
| 185 | +``` |
| 186 | + |
| 187 | +## Multi-line Descriptions |
| 188 | + |
| 189 | +Descriptions containing newlines are rendered properly in both `--help` output and generated documentation. This includes text blocks (Java 15+): |
| 190 | + |
| 191 | +```java |
| 192 | +@Option(name = "env", description = """ |
| 193 | + Target environment. |
| 194 | + Must be one of: dev, staging, prod. |
| 195 | + Defaults to the value of $APP_ENV.""") |
| 196 | +``` |
| 197 | + |
| 198 | +Leading indentation from text blocks is automatically stripped. |
0 commit comments