Crates.io | clappen |
lib.rs | clappen |
version | |
source | src |
created_at | 2024-12-09 17:25:30.468565 |
updated_at | 2024-12-12 09:13:27.820706 |
description | Clap flatten prefix macro |
homepage | |
repository | https://github.com/killzoner/clappen |
max_upload_size | |
id | 1477691 |
Cargo.toml error: | TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
Flatten prefix for
clap
Integrate flatten prefix in your clap
parsers easily.
For more details, see:
use clap::Parser;
// export is the name of the macro generated
#[clappen::clappen(export = nested)]
// this mod definition does not appear in the
// final generated code, it's just a convenient
// wrapper for item definitions
mod unused_mod {
#[derive(clap::Args, Debug, Clone)]
pub struct Remote {
#[arg(env, long)]
id: String,
}
impl Remote {
fn a_function(&self) -> String {
// this `self` reference will be rewritten
// to field prefixed with `test`, ie `self.test_id`.
format!("id: {:?}", self.id)
}
}
}
// export is the name of the macro generated
#[clappen::clappen(export = prefixed_struct_generator)]
// mod definition not used too
mod unused_mod {
#[derive(clap::Parser, Debug, Clone)]
#[command(version, about)]
pub struct Options {
#[arg(env, long)]
url: String,
#[command(flatten)]
// `apply` is the macro export used
// (defined with `Remote` struct earlier)
// `prefix` is optional
#[clappen_command(apply = nested, prefix = "test")]
nested: Remote,
}
}
// generate the default struct without prefix
prefixed_struct_generator!();
fn main() -> Result<(), Box<dyn std::error::Error>> {
let _ = Options::parse();
Ok(())
}
clap
unfortunately doesn't preserve field structure and prefix when flattening command
s.
See this issue for more in-depth explanation.
This crate allows fixing that while not requiring custom wrapper to the end clap
parser used. It's just a struct
macro generator that uses clap
default behaviour around arg
attribute.
See clap documentation for arg.
Providing custom long
or env
to your fields is not supported. See Roadmap.
References to fields with more than 1 nesting level won't work - like self.my_field_level1.my_field_level2
.
Generally this should not be needed because you want to get something out of your reusable struct parser (and Rust might get in your way for borrow-related things).
If you still want to do that, you can write custom getter functions, and the renamed fields will be picked in the impl
blocks.
Probably some edge cases are not covered. For example, clap
subcommand
s should be working, but it was not tested extensively as my use case is mainly reusing struct
s in a mono repository fashion.
long
/ env
prefix injection.clap
tighter and the code more complicated though.clappen_command
required with command(flatten)
even without prefix ?Because people work with copy/paste.
For example, if this was not required, you might write this
#[clappen::clappen(export = nested)]
mod m {
#[derive(clap::Args)]
pub struct Nested {}
}
#[clappen::clappen(export = copyable_opts)]
mod m {
#[derive(clap::Parser)]
#[command(version, about)]
pub struct CopyableOptions {
#[command(flatten)]
nested: Nested,
}
}
But then if you copy paste this and turn it to a reusable parser, you get this
#[clappen::clappen(export = nested)]
mod m {
#[derive(clap::Args)]
pub struct Nested {}
}
#[clappen::clappen(export = copyable_opts)]
mod m {
#[derive(clap::Args)]
pub struct CopyableOptions {
#[command(flatten)]
nested: Nested,
}
}
#[clappen::clappen(export = parser)]
mod m {
#[derive(clap::Parser)]
#[command(version, about)]
pub struct Options {
#[command(flatten)]
// You're back to original issue, prefix is
// not maintained because `clappen` was not provided
opts: CopyableOptions,
}
}
Making clappen_command
required for all flatten
items avoids having to think about that when refactoring, you know that your prefix will be maintained even when using a single struct without a prefix.
syn
, quote
and paste
.paste
but it is sadly now unmaintained.clap
and all its great features.