diff --git a/Cargo.lock b/Cargo.lock index 68283c33..bfcfc555 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,6 +300,16 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "clap_mangen" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e35a078f3aae828c9b7ad58e1631dab87e9dac40da19418f2219bbf3198aa5c" +dependencies = [ + "clap", + "roff", +] + [[package]] name = "clearscreen" version = "2.0.1" @@ -646,6 +656,7 @@ dependencies = [ "camino", "clap", "clap_complete", + "clap_mangen", "clearscreen", "command-group", "crossterm", @@ -1403,6 +1414,12 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "roff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index 1f1e8e0b..04b73609 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ camino = "1.1.4" # Clap 4.4 is the last version supporting Rust 1.72. clap = { version = "~4.4", features = ["derive", "wrap_help", "env", "string"] } clap_complete = "~4.4" +clap_mangen = { version = "=0.2.19", optional = true } clearscreen = "2.0.1" command-group = { version = "2.1.0", features = ["tokio", "with-tokio"] } crossterm = { version = "0.27.0", features = ["event-stream"] } diff --git a/nix/packages/ghciwatch.nix b/nix/packages/ghciwatch.nix index cd06c517..f4a29803 100644 --- a/nix/packages/ghciwatch.nix +++ b/nix/packages/ghciwatch.nix @@ -135,8 +135,31 @@ }; }; + ghciwatch-man = craneLib.buildPackage (releaseArgs + // { + pnameSuffix = "-man"; + + cargoExtraArgs = "--locked --features clap_mangen"; + + nativeBuildInputs = (releaseArgs.nativeBuildInputs or []) ++ [installShellFiles]; + + postInstall = + (releaseArgs.postInstall or "") + + lib.optionalString can-run-ghciwatch '' + manpages=$(mktemp -d) + ${run-ghciwatch} --generate-man-pages "$manpages" + for manpage in "$manpages"/*; do + installManPage "$manpage" + done + + rm -rf "$out/bin" + ''; + }); + ghciwatch-with-clap-markdown = craneLib.buildPackage (releaseArgs // { + pnameSuffix = "-cli-markdown"; + cargoExtraArgs = "--locked --features clap-markdown"; }); @@ -261,4 +284,16 @@ ]; }; in - craneLib.buildPackage releaseArgs + craneLib.buildPackage (releaseArgs + // { + postInstall = + (releaseArgs.postInstall or "") + + '' + cp -r ${ghciwatch-man}/share $out/share + + # For some reason this is needed to strip references: + # stripping references to cargoVendorDir from share/man/man1/ghciwatch.1.gz + # sed: couldn't open temporary file share/man/man1/sedwVs75O: Permission denied + chmod -R +w $out/share + ''; + }) diff --git a/src/cli.rs b/src/cli.rs index 14e6431b..d3d37110 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -101,6 +101,11 @@ pub struct Opts { #[arg(long, hide = true)] pub generate_markdown_help: bool, + /// Generate `man` pages in the given directory. + #[cfg(feature = "clap_mangen")] + #[arg(long, hide = true)] + pub generate_man_pages: Option, + /// Generate shell completions for the given shell. #[arg(long)] pub completions: Option, diff --git a/src/main.rs b/src/main.rs index 00d48b2a..d0cfb478 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,18 @@ async fn main() -> miette::Result<()> { return Ok(()); } + #[cfg(feature = "clap_mangen")] + if let Some(out_dir) = opts.generate_man_pages { + use miette::IntoDiagnostic; + use miette::WrapErr; + + let command = cli::Opts::command(); + clap_mangen::generate_to(command, out_dir) + .into_diagnostic() + .wrap_err("Failed to generate man pages")?; + return Ok(()); + } + if let Some(shell) = opts.completions { let mut command = cli::Opts::command(); clap_complete::generate(shell, &mut command, "ghciwatch", &mut std::io::stdout());