8.1 KiB
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 definitionsocktop_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:
- Includes the CLI definition file
- Uses
clap_mangento generate the man page - Saves it to
$OUT_DIR/man/*.1
The generation happens automatically during:
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:
# 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/binor/usr/local/bin - Installs man pages to
~/.local/share/man/man1or/usr/local/share/man/man1
Option 2: Manual Installation After Build
# 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:
# 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:
man socktop
man socktop_agent
If man socktop doesn't work after user installation, add to your shell rc:
# 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:
-
Edit the CLI definition in
src/cli.rs:/// Your new option description #[arg(short = 'x', long = "example")] pub example: bool, -
Rebuild to regenerate man pages:
cargo build --release -
Reinstall man pages:
./scripts/install-with-man.sh --man-only
The man pages will automatically reflect your changes!
CLI Definition Format
Basic Structure
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
/// 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
/// 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
- Write good doc comments in
cli.rs- they become man page content - Use
long_aboutfor detailed descriptions - Specify
value_namefor clarity (e.g.,<PORT>,<URL>) - Document environment variables in the option description
- Use
hide = truefor internal/test options - Keep descriptions concise but informative
- Rebuild after CLI changes to update man pages
Testing Man Page Generation
# 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:
cargo clean
cargo build -vv 2>&1 | grep build.rs
Can't find generated man page
Solution: Look in the correct build output:
find target -name "socktop.1" -type f
Man page content is outdated
Solution: Clean and rebuild:
cargo clean
cargo build --release
MANPATH not working
Solution: Verify the path is correct:
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
- clap_mangen documentation
- Manual man pages - The original manually written versions
- Quick Reference - Command cheat sheet