From f1bb96d73b1cfdf7e3204a09e5315ad21016a1a1 Mon Sep 17 00:00:00 2001 From: Aaron Allen Date: Mon, 23 Mar 2026 19:07:13 -0500 Subject: [PATCH] feat(cli): add man page generation via clap_mangen Closes #274 --- Cargo.lock | 17 +++++++++++++++++ Cargo.toml | 2 ++ src/bin/manpages.rs | 29 +++++++++++++++++++++++++++++ src/cli.rs | 2 +- src/lib.rs | 3 +++ src/main.rs | 4 +--- tasks/generate/manpages | 7 +++++++ 7 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 src/bin/manpages.rs create mode 100644 src/lib.rs create mode 100755 tasks/generate/manpages diff --git a/Cargo.lock b/Cargo.lock index 78b73ad..d651c52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -274,6 +274,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "clap_mangen" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30ffc187e2e3aeafcd1c6e2aa416e29739454c0ccaa419226d5ecd181f2d78" +dependencies = [ + "clap", + "roff", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -475,6 +485,7 @@ dependencies = [ "chrono", "clap", "clap_complete", + "clap_mangen", "dialoguer", "dir_spec", "doing-config", @@ -1706,6 +1717,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "roff" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf2048e0e979efb2ca7b91c4f1a8d77c91853e9b987c94c555668a8994915ad" + [[package]] name = "rustc-hash" version = "2.1.1" diff --git a/Cargo.toml b/Cargo.toml index 28e761b..c7a7639 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ assert_cmd = "2" chrono = { features = ["serde"], version = "0.4" } clap = { features = ["derive", "suggestions"], version = "4" } clap_complete = "4" +clap_mangen = "0.2" dialoguer = "0.12" dir_spec = "0.5" doing-config = { path = "crates/config" } @@ -73,6 +74,7 @@ yansi = { features = ["detect-env", "detect-tty", "hyperlink"], version = "1" } chrono.workspace = true clap.workspace = true clap_complete.workspace = true +clap_mangen.workspace = true dialoguer.workspace = true dir_spec.workspace = true doing-config.workspace = true diff --git a/src/bin/manpages.rs b/src/bin/manpages.rs new file mode 100644 index 0000000..c00d5b2 --- /dev/null +++ b/src/bin/manpages.rs @@ -0,0 +1,29 @@ +use std::{fs, path::PathBuf}; + +use clap::CommandFactory; +use clap_mangen::Man; + +fn main() { + let out_dir = PathBuf::from(std::env::args().nth(1).unwrap_or_else(|| "target/man".into())); + fs::create_dir_all(&out_dir).expect("failed to create man page output directory"); + + let cmd = doing::cli::Cli::command(); + generate_manpage(&cmd, "doing", &out_dir); + + for subcommand in cmd.get_subcommands() { + if subcommand.is_hide_set() { + continue; + } + let name = format!("doing-{}", subcommand.get_name()); + generate_manpage(subcommand, &name, &out_dir); + } +} + +fn generate_manpage(cmd: &clap::Command, name: &str, out_dir: &PathBuf) { + let man = Man::new(cmd.clone()); + let mut buf = Vec::new(); + man.render(&mut buf).expect("failed to render man page"); + + let path = out_dir.join(format!("{name}.1")); + fs::write(&path, buf).expect("failed to write man page"); +} diff --git a/src/cli.rs b/src/cli.rs index ad2a58c..52dc963 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -100,7 +100,7 @@ impl AppContext { name = "doing", version = env!("CARGO_PKG_VERSION"), )] -pub(crate) struct Cli { +pub struct Cli { /// Colored output #[arg(long, action = ArgAction::SetTrue, overrides_with = "no_color", global = true)] color: bool, diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1151427 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cli; + +pub use doing_error::{Error, Result}; diff --git a/src/main.rs b/src/main.rs index 825fcf3..c7f6cd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,4 @@ -mod cli; - -pub use doing_error::{Error, Result}; +use doing::cli; fn main() { if let Err(e) = cli::run() { diff --git a/tasks/generate/manpages b/tasks/generate/manpages new file mode 100755 index 0000000..b0502a3 --- /dev/null +++ b/tasks/generate/manpages @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +#MISE description="Generate man pages from clap definitions" + +set -e + +cargo run --bin manpages -- target/man +echo "Man pages generated in target/man/" -- knotmirror 0.0.1