zoi/cmd/
gen_man.rs

1use crate::cli::Cli;
2use clap::{Command, CommandFactory};
3use clap_mangen::Man;
4use std::env;
5use std::fs;
6use std::io;
7use std::path::{Path, PathBuf};
8
9pub fn run() -> io::Result<()> {
10    let out_dir = env::var("OUT_DIR").unwrap_or_else(|_| "manuals".to_string());
11    let out_path = PathBuf::from(out_dir);
12    fs::create_dir_all(&out_path)?;
13
14    let app = Cli::command();
15    println!("Generating man pages in {}...", out_path.display());
16
17    generate_man_page(&app, &out_path)?;
18
19    for sub_command in app.get_subcommands() {
20        generate_man_pages_recursive(sub_command, &out_path, app.get_name())?;
21    }
22
23    println!(
24        "\nSuccessfully generated man pages in '{}'.",
25        out_path.display()
26    );
27    Ok(())
28}
29
30fn generate_man_pages_recursive(
31    cmd: &Command,
32    out_path: &Path,
33    parent_name: &str,
34) -> io::Result<()> {
35    if cmd.is_hide_set() {
36        return Ok(());
37    }
38
39    let full_name = format!("{}-{}", parent_name, cmd.get_name());
40    let leaked_name: &'static str = Box::leak(full_name.into_boxed_str());
41    let new_cmd = cmd.clone().name(leaked_name);
42    generate_man_page(&new_cmd, out_path)?;
43
44    for sub_cmd in new_cmd.get_subcommands() {
45        generate_man_pages_recursive(sub_cmd, out_path, leaked_name)?;
46    }
47
48    Ok(())
49}
50
51fn generate_man_page(app: &Command, out_path: &Path) -> io::Result<()> {
52    let name = app.get_name();
53    let out_file = out_path.join(format!("{}.1", name));
54
55    let man = Man::new(app.clone());
56    let mut buffer = Vec::<u8>::new();
57    man.render(&mut buffer)?;
58
59    fs::write(&out_file, &buffer)?;
60    println!("- {}", out_file.display());
61
62    Ok(())
63}