//! man: generate roff man pages from the clap definition (issue #41). //! 'am man' prints am.1 for the whole CLI; 'am man ' prints one //! page; '--output DIR' writes am.1 plus one am-.1 per command. use super::*; use anyhow::Context; use clap::CommandFactory; use std::io::Write; use std::path::Path; pub fn run(app: &App, command: Option<&str>, output: Option<&Path>) -> Result { let mut cmd = crate::cli::Cli::command(); if app.dry_run() { app.log.dry("would generate man pages"); return Ok(0); } match command { Some(name) => { let sub = cmd.find_subcommand_mut(name).ok_or_else(|| { anyhow!( "unknown command '{name}' — 'am help commands' lists every command" ) })?; let man = clap_mangen::Man::new(sub.clone()).title(format!("am-{name}")); match output { Some(dir) => { write_page(dir, &format!("am-{name}"), &man)?; app.log.success(&format!( "man page written to {}", dir.join(format!("am-{name}.1")).display() )); } None => man.render(&mut std::io::stdout())?, } } None => match output { Some(dir) => { let main = clap_mangen::Man::new(cmd.clone()); write_page(dir, "am", &main)?; for sub in cmd.get_subcommands() { if sub.is_hide_set() { continue; } let name = format!("am-{}", sub.get_name()); let m = clap_mangen::Man::new(sub.clone()).title(name.clone()); write_page(dir, &name, &m)?; } app.log.success(&format!( "man pages written to {} (am.1 + {} pages)", dir.display(), cmd.get_subcommands().count() )); } None => clap_mangen::Man::new(cmd).render(&mut std::io::stdout())?, }, } Ok(0) } fn write_page(dir: &Path, name: &str, man: &clap_mangen::Man) -> Result<()> { std::fs::create_dir_all(dir) .with_context(|| format!("cannot create {}", dir.display()))?; let path = dir.join(format!("{name}.1")); let mut file = std::fs::File::create(&path) .with_context(|| format!("cannot create {}", path.display()))?; man.render(&mut file) .with_context(|| format!("cannot render {}", path.display()))?; file.flush().ok(); Ok(()) }