From 13cc7e05edac05f5ef7637b6aba4ba83404b936d Mon Sep 17 00:00:00 2001 From: Emil Engler Date: Sun, 16 Apr 2023 10:47:15 +0200 Subject: [PATCH] invoke `man(1)` when requesting help This commit invokes `man(1)` when requesting help and emits the built-in manual, if the manual page is not found on the system. --- Cargo.lock | 4 ++-- Cargo.toml | 3 +++ build.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 2 ++ src/main.rs | 8 +++++++- 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 build.rs diff --git a/Cargo.lock b/Cargo.lock index 916a912..8f94fa8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" dependencies = [ "backtrace", ] diff --git a/Cargo.toml b/Cargo.toml index 8d9449f..84a3131 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,9 @@ paste = "1.0.11" log = { version = "0.4.17", optional = true } env_logger = { version = "0.10.0", optional = true } +[build-dependencies] +anyhow = "1.0.70" + [dev-dependencies] criterion = "0.3.5" test_bin = "0.4.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..7819a6a --- /dev/null +++ b/build.rs @@ -0,0 +1,53 @@ +use anyhow::bail; +use anyhow::Result; +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; +use std::process::Command; + +/// Invokes a troff compiler to compile a manual page +fn render_man(compiler: &str, man: &str) -> Result { + let out = Command::new(compiler).args(["-Tascii", man]).output()?; + if !out.status.success() { + bail!("{} returned an error", compiler); + } + + Ok(String::from_utf8(out.stdout)?) +} + +/// Generates the manual page +fn generate_man() -> String { + // This function is purposely stupid and redundant + + let man = render_man("mandoc", "./doc/rosenpass.1"); + if man.is_ok() { + return man.unwrap(); + } + + let man = render_man("groff", "./doc/rosenpass.1"); + if man.is_ok() { + return man.unwrap(); + } + + // TODO: Link to online manual here + "Cannot render manual page\n".into() +} + +fn man() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let man = generate_man(); + let path = out_dir.join("rosenpass.1.ascii"); + + let mut file = File::create(&path).unwrap(); + file.write_all(man.as_bytes()).unwrap(); + + println!("cargo:rustc-env=ROSENPASS_MAN={}", path.display()); +} + +fn main() { + // For now, rerun the build script on every time, as the build script + // is not very expensive right now. + println!("cargo:rerun-if-changed=./"); + man(); +} diff --git a/flake.nix b/flake.nix index b3fd5f6..a98861a 100644 --- a/flake.nix +++ b/flake.nix @@ -61,6 +61,7 @@ # source files relevant for rust src = pkgs.lib.sourceByRegex ./. [ "Cargo\\.(toml|lock)" + "build.rs" "(src|benches)(/.*\\.(rs|md))?" "rp" ]; @@ -111,6 +112,7 @@ nativeBuildInputs = with pkgs; [ p.stdenv.cc cmake # for oqs build in the oqs-sys crate + mandoc # for the built-in manual makeWrapper # for the rp shellscript pkg-config # let libsodium-sys-stable find libsodium removeReferencesTo diff --git a/src/main.rs b/src/main.rs index 5fc86d1..2e8acd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -287,7 +287,13 @@ pub fn rosenpass_main() -> Result<()> { /// Print the usage information pub fn cmd_help() -> Result<()> { - eprint!(include_str!("usage.md"), env!("CARGO_BIN_NAME")); + let man_cmd = Command::new("man").args(["1", "rosenpass"]).status(); + if man_cmd.is_ok() && man_cmd.unwrap().success() { + return Ok(()); + } + + // Print the compiled manual + eprint!(include_str!(env!("ROSENPASS_MAN"))); Ok(()) }