Skip to content

Commit bd43eea

Browse files
committed
Add documentation generation page and update migration guide
New page: Documentation Generation - Quick start with --aesh-doc flag - Programmatic API with DocumentationGenerator builder - Antora integration with cross-reference prefixes and nav files - Generated sections documentation (NAME, SYNOPSIS, DESCRIPTION, OPTIONS, ARGUMENTS, COMMANDS) - HelpSectionProvider content inclusion - Option rendering features - Output format examples for both AsciiDoc and Markdown - Multi-line description and text block support Migration guide: - Added Documentation Generation section with comparison to picocli's ManPageGenerator and code examples
1 parent 97a1e68 commit bd43eea

2 files changed

Lines changed: 222 additions & 0 deletions

File tree

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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.

content/docs/aesh/migrating-from-picocli.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,30 @@ $ myapp --aesh-completion-install
256256

257257
Picocli's `AutoComplete` only supports bash. Aesh supports bash, zsh, and fish, with both static and dynamic (callback-based) completion scripts.
258258

259+
## Documentation Generation
260+
261+
Aesh can generate AsciiDoc or Markdown documentation from command metadata, similar to picocli's `ManPageGenerator`. See [Documentation Generation](../documentation-generation) for details.
262+
263+
```bash
264+
# Generate AsciiDoc documentation
265+
$ myapp --aesh-doc asciidoc > docs/myapp.adoc
266+
267+
# Generate Markdown
268+
$ myapp --aesh-doc markdown > docs/myapp.md
269+
```
270+
271+
For Antora-based documentation sites, the programmatic API supports cross-reference prefixes and navigation file generation:
272+
273+
```java
274+
DocumentationGenerator.builder()
275+
.commandClass(MyCommand.class)
276+
.outputDir(new File("docs/pages"))
277+
.crossRefPrefix("myapp:cli:")
278+
.navFile(new File("docs/nav.adoc"))
279+
.format(DocFormat.ASCIIDOC)
280+
.generate();
281+
```
282+
259283
## Annotation Processor
260284

261285
For maximum startup performance, add the [annotation processor](../annotation-processor) to eliminate all runtime reflection:

0 commit comments

Comments
 (0)