From 05e8698bcfdd7ffd62706fb01a0b3b7cacf35f65 Mon Sep 17 00:00:00 2001 From: Cameron Hart Date: Thu, 4 Jun 2026 20:27:57 +1200 Subject: [PATCH 1/2] Convert arg parsing from clap to argh. --- Cargo.lock | 96 ++++++++++++++++++----------------------------------- Cargo.toml | 3 +- src/main.rs | 71 ++++++++++++++++++++++++--------------- 3 files changed, 79 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 557bb8e..537e84d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,16 +18,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] -name = "autocfg" -version = "1.5.0" +name = "argh" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "211818e820cda9ca6f167a64a5c808837366a6dfd807157c64c1304c486cd033" +dependencies = [ + "argh_derive", + "argh_shared", +] [[package]] -name = "bitflags" -version = "1.3.2" +name = "argh_derive" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "c442a9d18cef5dde467405d27d461d080d68972d6d0dfd0408265b6749ec427d" +dependencies = [ + "argh_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "argh_shared" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ade012bac4db278517a0132c8c10c6427025868dca16c801087c28d5a411f1" +dependencies = [ + "serde", +] [[package]] name = "bitflags" @@ -71,34 +90,13 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "bitflags 1.3.2", - "clap_lex", - "indexmap 1.9.3", - "once_cell", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "codegen" version = "0.1.1" dependencies = [ "anyhow", - "clap", + "argh", + "argh_derive", "git2", "globset", "rustfmt-wrapper", @@ -231,7 +229,7 @@ version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.9.1", + "bitflags", "libc", "libgit2-sys", "log", @@ -257,17 +255,11 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.9.1", + "bitflags", "ignore", "walkdir", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.15.4" @@ -406,16 +398,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.10.0" @@ -423,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown", ] [[package]] @@ -508,12 +490,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -651,7 +627,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.1", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -800,12 +776,6 @@ dependencies = [ "unic-segment", ] -[[package]] -name = "textwrap" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" - [[package]] name = "thiserror" version = "1.0.69" @@ -883,7 +853,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.10.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -1196,7 +1166,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.1", + "bitflags", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4687206..518f384 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" [dependencies] anyhow = { version = "1" } -clap = { version = "3", default-features = false, features = ["cargo", "std"] } +argh = "0.1" +argh_derive = "0.1" git2 = { version = "0.18", default-features = false } globset = { version = "0.4", default-features = false } rustfmt-wrapper = { version = "0.2" } diff --git a/src/main.rs b/src/main.rs index c15b10c..04ba0d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Context}; -use clap::{arg, command}; +use argh::FromArgs; use rustfmt_wrapper::rustfmt; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -167,31 +167,48 @@ fn find_config_file() -> anyhow::Result { )) } +#[derive(FromArgs, PartialEq, Debug)] +/// Codegen - Generate Rust code from templates +struct CliArgs { + /// output file paths (glob pattern) + #[argh(positional, hidden_help)] + glob: Option, + + /// force overwrite existing files + #[argh(switch, short = 'f')] + force: bool, + + /// output to stdout + #[argh(switch, short = 's')] + stdout: bool, + + /// skip formatting output + #[argh(switch, short = 'n')] + nofmt: bool, + + /// check mode - compare generated files with existing + #[argh(switch)] + check: bool, + + /// verbose output + #[argh(switch, short = 'v')] + verbose: bool, +} + fn main() -> anyhow::Result<()> { - let matches = command!() - .arg(arg!([GLOB])) - .arg(arg!(-f - -force)) - .arg(arg!(-s - -stdout)) - .arg(arg!(-n - -nofmt)) - .arg(arg!(--check)) - .arg(arg!(-v - -verbose)) - .get_matches(); - - let force = matches.is_present("force"); - let stdout = matches.is_present("stdout"); - let fmt_output = !matches.is_present("nofmt"); - let output_path_glob = matches.value_of("GLOB"); - let check = matches.is_present("check"); - let verbose = matches.is_present("verbose"); - - if stdout && output_path_glob.is_none() { + let args: CliArgs = argh::from_env(); + + let fmt_output = !args.nofmt; + let output_path_glob = args.glob; + + if args.stdout && output_path_glob.is_none() { // TODO: What if the glob matches multiple files? bail!("specify a single file to output to stdout."); } - let glob = if let Some(output_path_glob) = output_path_glob { + let glob = if let Some(ref output_path_glob) = output_path_glob { Some( - globset::Glob::new(output_path_glob) + globset::Glob::new(output_path_glob.as_str()) .context("failed to compile glob")? .compile_matcher(), ) @@ -255,14 +272,14 @@ fn main() -> anyhow::Result<()> { let mut output_differences = 0; for output_path in output_paths { - if !check { + if !args.check { println!("generating {output_path}"); } let context = output_pairs.get(output_path).unwrap(); let template_path = context.get("template_path").unwrap().as_str().unwrap(); - if !(check || force || stdout) && is_modified(&repo, output_path)? { + if !(args.check || args.force || args.stdout) && is_modified(&repo, output_path)? { bail!( "{} is already modified, use `-f` to force overwrite or revert local changes.", output_path @@ -271,7 +288,7 @@ fn main() -> anyhow::Result<()> { let mut output_str = generate_file(&tera, context, template_path)?; - if fmt_output || check { + if fmt_output || args.check { output_str = rustfmt(&output_str).context("rustfmt failed")?; } @@ -280,13 +297,13 @@ fn main() -> anyhow::Result<()> { let output_dir = full_output_path.parent().unwrap(); std::fs::create_dir_all(output_dir)?; - if check { + if args.check { match std::fs::read_to_string(&full_output_path) { Ok(original_str) => { if output_str != original_str { println!("'{output_path}' is different"); output_differences += 1; - } else if verbose { + } else if args.verbose { println!("'{output_path}' is the same"); } } @@ -298,7 +315,7 @@ fn main() -> anyhow::Result<()> { continue; } - if stdout { + if args.stdout { print!("{output_str}"); continue; } @@ -307,7 +324,7 @@ fn main() -> anyhow::Result<()> { .with_context(|| format!("failed to write {}", full_output_path.display()))?; } - if check && output_differences > 0 { + if args.check && output_differences > 0 { bail!("{output_differences} files were different"); } From 503887b69dd4cbb7d221ef421ccf8945c16f4002 Mon Sep 17 00:00:00 2001 From: Cameron Hart Date: Thu, 4 Jun 2026 21:54:28 +1200 Subject: [PATCH 2/2] fmt --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 04ba0d9..b9e2aaa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -197,7 +197,7 @@ struct CliArgs { fn main() -> anyhow::Result<()> { let args: CliArgs = argh::from_env(); - + let fmt_output = !args.nofmt; let output_path_glob = args.glob;