320 lines
8.1 KiB
Markdown
320 lines
8.1 KiB
Markdown
# Auto-Generated Man Pages
|
|
|
|
This document explains how man pages are automatically generated from the CLI definitions using `clap` and `clap_mangen`.
|
|
|
|
## Overview
|
|
|
|
Starting from version 1.50.0+, socktop uses **clap** for CLI parsing and **clap_mangen** to automatically generate man pages at build time. This approach has several advantages:
|
|
|
|
✅ Man pages are always in sync with the actual CLI
|
|
✅ Single source of truth (CLI definitions)
|
|
✅ No manual maintenance of separate man page files
|
|
✅ Generated during `cargo build` automatically
|
|
✅ Can be installed alongside binaries
|
|
|
|
## How It Works
|
|
|
|
### 1. CLI Definitions
|
|
|
|
Both `socktop` and `socktop_agent` use clap's derive macros to define their CLI:
|
|
|
|
- **`socktop/src/cli.rs`** - Client CLI definition
|
|
- **`socktop_agent/src/cli.rs`** - Agent CLI definition
|
|
|
|
These files use clap's attributes to specify:
|
|
- Arguments and options
|
|
- Help text and descriptions
|
|
- Value names and types
|
|
- Environment variable support
|
|
- Hidden options (for testing)
|
|
|
|
### 2. Build-Time Generation
|
|
|
|
Each crate has a `build.rs` script that:
|
|
1. Includes the CLI definition file
|
|
2. Uses `clap_mangen` to generate the man page
|
|
3. Saves it to `$OUT_DIR/man/*.1`
|
|
|
|
The generation happens automatically during:
|
|
```bash
|
|
cargo build
|
|
cargo build --release
|
|
cargo install
|
|
```
|
|
|
|
### 3. Generated Man Pages Location
|
|
|
|
After building, man pages are located at:
|
|
```
|
|
target/debug/build/socktop-*/out/man/socktop.1
|
|
target/debug/build/socktop_agent-*/out/man/socktop_agent.1
|
|
|
|
# Or for release builds:
|
|
target/release/build/socktop-*/out/man/socktop.1
|
|
target/release/build/socktop_agent-*/out/man/socktop_agent.1
|
|
```
|
|
|
|
## Installation Options
|
|
|
|
### Option 1: Use the Installation Script (Recommended)
|
|
|
|
The `scripts/install-with-man.sh` script builds the binaries, extracts the generated man pages, and installs everything:
|
|
|
|
```bash
|
|
# User installation (no sudo)
|
|
./scripts/install-with-man.sh
|
|
|
|
# System-wide installation (requires sudo)
|
|
sudo ./scripts/install-with-man.sh --system
|
|
|
|
# Only install man pages (after building)
|
|
./scripts/install-with-man.sh --man-only
|
|
```
|
|
|
|
This script:
|
|
- Builds the project in release mode
|
|
- Extracts generated man pages from `OUT_DIR`
|
|
- Installs binaries to `~/.cargo/bin` or `/usr/local/bin`
|
|
- Installs man pages to `~/.local/share/man/man1` or `/usr/local/share/man/man1`
|
|
|
|
### Option 2: Manual Installation After Build
|
|
|
|
```bash
|
|
# Build the project
|
|
cargo build --release
|
|
|
|
# Find generated man pages
|
|
SOCKTOP_MAN=$(find target/release/build/socktop-*/out/man/socktop.1 | head -1)
|
|
AGENT_MAN=$(find target/release/build/socktop_agent-*/out/man/socktop_agent.1 | head -1)
|
|
|
|
# Install to user directory
|
|
mkdir -p ~/.local/share/man/man1
|
|
cp "$SOCKTOP_MAN" ~/.local/share/man/man1/
|
|
cp "$AGENT_MAN" ~/.local/share/man/man1/
|
|
|
|
# Or install system-wide
|
|
sudo mkdir -p /usr/local/share/man/man1
|
|
sudo cp "$SOCKTOP_MAN" /usr/local/share/man/man1/
|
|
sudo cp "$AGENT_MAN" /usr/local/share/man/man1/
|
|
sudo mandb # Update man database
|
|
```
|
|
|
|
### Option 3: View Without Installing
|
|
|
|
You can view the generated man pages directly:
|
|
|
|
```bash
|
|
# After building
|
|
man -l $(find target/release/build/socktop-*/out/man/socktop.1 | head -1)
|
|
man -l $(find target/release/build/socktop_agent-*/out/man/socktop_agent.1 | head -1)
|
|
```
|
|
|
|
## Viewing Installed Man Pages
|
|
|
|
After installation:
|
|
|
|
```bash
|
|
man socktop
|
|
man socktop_agent
|
|
```
|
|
|
|
If `man socktop` doesn't work after user installation, add to your shell rc:
|
|
|
|
```bash
|
|
# For bash
|
|
echo 'export MANPATH="$HOME/.local/share/man:$MANPATH"' >> ~/.bashrc
|
|
source ~/.bashrc
|
|
|
|
# For zsh
|
|
echo 'export MANPATH="$HOME/.local/share/man:$MANPATH"' >> ~/.zshrc
|
|
source ~/.zshrc
|
|
```
|
|
|
|
## Updating CLI and Man Pages
|
|
|
|
When you need to update the CLI or man pages:
|
|
|
|
1. **Edit the CLI definition** in `src/cli.rs`:
|
|
```rust
|
|
/// Your new option description
|
|
#[arg(short = 'x', long = "example")]
|
|
pub example: bool,
|
|
```
|
|
|
|
2. **Rebuild** to regenerate man pages:
|
|
```bash
|
|
cargo build --release
|
|
```
|
|
|
|
3. **Reinstall** man pages:
|
|
```bash
|
|
./scripts/install-with-man.sh --man-only
|
|
```
|
|
|
|
The man pages will automatically reflect your changes!
|
|
|
|
## CLI Definition Format
|
|
|
|
### Basic Structure
|
|
|
|
```rust
|
|
use clap::Parser;
|
|
|
|
#[derive(Parser, Debug)]
|
|
#[command(
|
|
name = "myapp",
|
|
version,
|
|
author,
|
|
about = "Short description",
|
|
long_about = "Longer description that appears in man page and --help"
|
|
)]
|
|
pub struct Cli {
|
|
/// Short description of this option
|
|
///
|
|
/// Longer description that appears in the man page.
|
|
/// Can span multiple lines.
|
|
#[arg(short = 't', long = "thing", value_name = "VALUE")]
|
|
pub thing: Option<String>,
|
|
|
|
/// Boolean flag
|
|
#[arg(long)]
|
|
pub flag: bool,
|
|
|
|
/// Hidden option (won't appear in man page or --help)
|
|
#[arg(long, hide = true)]
|
|
pub secret: bool,
|
|
}
|
|
```
|
|
|
|
### Environment Variable Support
|
|
|
|
```rust
|
|
/// Port to listen on
|
|
///
|
|
/// Can also be set via MYAPP_PORT environment variable.
|
|
#[arg(short = 'p', long = "port", env = "MYAPP_PORT")]
|
|
pub port: Option<u16>,
|
|
```
|
|
|
|
### Value Parsing
|
|
|
|
```rust
|
|
/// Custom parser
|
|
#[arg(long, value_parser = parse_custom)]
|
|
pub custom: Option<String>,
|
|
|
|
fn parse_custom(s: &str) -> Result<String, String> {
|
|
// Custom validation logic
|
|
Ok(s.to_string())
|
|
}
|
|
```
|
|
|
|
## Advantages Over Manual Man Pages
|
|
|
|
| Feature | Auto-Generated | Manual |
|
|
|---------|---------------|--------|
|
|
| Always in sync with CLI | ✅ Yes | ❌ Manual updates required |
|
|
| Single source of truth | ✅ Yes | ❌ Duplicated info |
|
|
| Maintenance effort | ✅ Low | ❌ High |
|
|
| Consistency | ✅ Guaranteed | ❌ Can drift |
|
|
| Generated at build time | ✅ Yes | ❌ Separate process |
|
|
| Works with `--help` | ✅ Same source | ❌ Separate |
|
|
| Rich formatting | ⚠️ Good | ✅ Full control |
|
|
|
|
## Comparison with Manual Man Pages
|
|
|
|
The project also includes manually written man pages in `docs/man/` for comparison and as templates. These are more detailed and include additional sections like:
|
|
|
|
- EXAMPLES with complex scenarios
|
|
- SECURITY CONSIDERATIONS
|
|
- PLATFORM NOTES
|
|
- Systemd integration guides
|
|
- Troubleshooting tips
|
|
|
|
The auto-generated man pages from clap are excellent for:
|
|
- Options and arguments
|
|
- Basic descriptions
|
|
- Version and author info
|
|
- Environment variables
|
|
|
|
But may be limited for:
|
|
- Complex examples
|
|
- Extensive narrative documentation
|
|
- Custom formatting
|
|
- Additional reference sections
|
|
|
|
## Best Practices
|
|
|
|
1. **Write good doc comments** in `cli.rs` - they become man page content
|
|
2. **Use `long_about`** for detailed descriptions
|
|
3. **Specify `value_name`** for clarity (e.g., `<PORT>`, `<URL>`)
|
|
4. **Document environment variables** in the option description
|
|
5. **Use `hide = true`** for internal/test options
|
|
6. **Keep descriptions concise** but informative
|
|
7. **Rebuild after CLI changes** to update man pages
|
|
|
|
## Testing Man Page Generation
|
|
|
|
```bash
|
|
# Clean build to ensure regeneration
|
|
cargo clean
|
|
|
|
# Build and check for man page warning
|
|
cargo build --release 2>&1 | grep "Man page generated"
|
|
|
|
# View the generated man page
|
|
man -l $(find target/release/build/socktop-*/out/man/socktop.1 | head -1)
|
|
|
|
# Check for errors
|
|
lexgrog $(find target/release/build/socktop-*/out/man/socktop.1 | head -1)
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Man page not generated
|
|
|
|
**Solution:** Check that `build.rs` ran successfully:
|
|
```bash
|
|
cargo clean
|
|
cargo build -vv 2>&1 | grep build.rs
|
|
```
|
|
|
|
### Can't find generated man page
|
|
|
|
**Solution:** Look in the correct build output:
|
|
```bash
|
|
find target -name "socktop.1" -type f
|
|
```
|
|
|
|
### Man page content is outdated
|
|
|
|
**Solution:** Clean and rebuild:
|
|
```bash
|
|
cargo clean
|
|
cargo build --release
|
|
```
|
|
|
|
### MANPATH not working
|
|
|
|
**Solution:** Verify the path is correct:
|
|
```bash
|
|
echo $MANPATH
|
|
man -w # Show current man paths
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements:
|
|
|
|
- [ ] Add more detailed examples section using clap's `after_help`
|
|
- [ ] Generate shell completions alongside man pages
|
|
- [ ] Create a custom man page template with additional sections
|
|
- [ ] Package man pages in release artifacts
|
|
- [ ] Auto-install man pages during `cargo install`
|
|
|
|
## See Also
|
|
|
|
- [clap documentation](https://docs.rs/clap/)
|
|
- [clap_mangen documentation](https://docs.rs/clap_mangen/)
|
|
- [Manual man pages](man/README.md) - The original manually written versions
|
|
- [Quick Reference](QUICK_REFERENCE.md) - Command cheat sheet |