From 5bb3a282c3a2e82c3f0c38e2e614db88ff063efc Mon Sep 17 00:00:00 2001 From: Bauke Date: Sun, 6 Nov 2022 18:44:23 +0100 Subject: [PATCH] Generate the subcommands usage reference automatically. --- hooked-cli/source/cli/cli_reference.rs | 51 +++++++++++++++++++ hooked-cli/source/cli/mod.rs | 16 ++++++ hooked-cli/source/main.rs | 5 ++ hooked-cli/source/templates/cli-reference.txt | 11 ++++ 4 files changed, 83 insertions(+) create mode 100644 hooked-cli/source/cli/cli_reference.rs create mode 100644 hooked-cli/source/templates/cli-reference.txt diff --git a/hooked-cli/source/cli/cli_reference.rs b/hooked-cli/source/cli/cli_reference.rs new file mode 100644 index 0000000..7bc5b90 --- /dev/null +++ b/hooked-cli/source/cli/cli_reference.rs @@ -0,0 +1,51 @@ +//! The `cli-reference` subcommand, only available in debug mode. + +use std::{fs::write, process::Command, str}; + +use { + color_eyre::Result, + hooked_config::Config, + tera::{Context, Tera}, +}; + +use crate::cli::CliReferenceArgs; + +const REFERENCE_TEMPLATE: &str = include_str!("../templates/cli-reference.txt"); + +/// The `cli-reference` subcommand. +pub fn hooked_cli_reference( + _config: Config, + args: CliReferenceArgs, +) -> Result<()> { + let out_path = if args.output.is_dir() { + args.output.join("cli-reference.txt") + } else { + args.output + }; + + let commands = { + let mut commands = vec![]; + let commands_to_document = &["install", "run", "uninstall"]; + + for command_name in commands_to_document { + let output = Command::new("cargo") + .env("NO_COLOR", "1") + .args(&["run", "-q", "--", command_name, "--help"]) + .output() + .unwrap(); + let usage = str::from_utf8(&output.stdout).unwrap().trim().to_string(); + commands.push((command_name.to_string(), usage)) + } + + commands + }; + + let mut context = Context::new(); + context.insert("commands", &commands); + write( + &out_path, + Tera::one_off(REFERENCE_TEMPLATE, &context, false)?, + )?; + + Ok(()) +} diff --git a/hooked-cli/source/cli/mod.rs b/hooked-cli/source/cli/mod.rs index 6061b78..6467640 100644 --- a/hooked-cli/source/cli/mod.rs +++ b/hooked-cli/source/cli/mod.rs @@ -4,10 +4,14 @@ use std::path::PathBuf; use clap::{Args as Arguments, Parser, Subcommand}; +#[cfg(debug_assertions)] +mod cli_reference; mod install; mod run; mod uninstall; +#[cfg(debug_assertions)] +pub use cli_reference::hooked_cli_reference; pub use install::hooked_install; pub use run::hooked_run; pub use uninstall::hooked_uninstall; @@ -37,6 +41,10 @@ pub enum MainSubcommands { /// Manually run hooks. Run(RunArgs), + + #[cfg(debug_assertions)] + /// Generate the CLI reference file for the mdBook. + CliReference(CliReferenceArgs), } /// The `install` subcommand arguments. @@ -62,3 +70,11 @@ pub struct RunArgs { #[clap(value_parser = crate::HOOK_TYPES)] pub hook_type: String, } + +/// The `cli-reference` subcommand arguments. +#[derive(Debug, Arguments)] +pub struct CliReferenceArgs { + /// Path where the CLI reference file should be generated. + #[clap(short, long, default_value = "hooked-book/source/")] + pub output: PathBuf, +} diff --git a/hooked-cli/source/main.rs b/hooked-cli/source/main.rs index d0a767c..e70b765 100644 --- a/hooked-cli/source/main.rs +++ b/hooked-cli/source/main.rs @@ -40,6 +40,11 @@ fn main() -> Result<()> { MainSubcommands::Run(sub_args) => { cli::hooked_run(config, sub_args.hook_type)?; } + + #[cfg(debug_assertions)] + MainSubcommands::CliReference(sub_args) => { + cli::hooked_cli_reference(config, sub_args)?; + } } Ok(()) diff --git a/hooked-cli/source/templates/cli-reference.txt b/hooked-cli/source/templates/cli-reference.txt new file mode 100644 index 0000000..d882794 --- /dev/null +++ b/hooked-cli/source/templates/cli-reference.txt @@ -0,0 +1,11 @@ +This file is automatically generated using the cli-reference subcommand. +Use `cargo run -- cli-reference` to generate it. + +{% for command in commands %} +{%- set name = command.0 -%} +{%- set usage = command.1 -%} +// ANCHOR: {{ name }} +$ hooked {{ name }} --help +{{ usage }} +// ANCHOR_END: {{ name }} +{% endfor %}